package com.atmilan.quartz.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atmilan.quartz.config.DelloglioXmlSaxHandler;
import com.atmilan.quartz.config.MybatisPlusConfig;
import com.atmilan.quartz.config.RestTemplateConfig;
import com.atmilan.quartz.constant.Constants;
import com.atmilan.quartz.constant.enums.BarCodeEnum;
import com.atmilan.quartz.constant.enums.OrangeChannelTypeEnum;
import com.atmilan.quartz.constant.enums.ProductTypeEnum;
import com.atmilan.quartz.constant.enums.StockAreaTempEnum;
import com.atmilan.quartz.model.dto.bellettini.BellettiniProductResDTO;
import com.atmilan.quartz.model.dto.buyer.BuyerProductResDTO;
import com.atmilan.quartz.model.dto.buyer.BuyerProductResDTO.Product;
import com.atmilan.quartz.model.dto.buyer.BuyerProductResDTO.ProductSku;
import com.atmilan.quartz.model.dto.carotta.CarottaProductResDTO;
import com.atmilan.quartz.model.dto.coltorti.ColtortiProductResDTO;
import com.atmilan.quartz.model.dto.delloglio.DelloglioProductResDTO;
import com.atmilan.quartz.model.dto.folli.FolliProductResDTO;
import com.atmilan.quartz.model.dto.folli.FolliProductResDTO.FolliGoodsRes;
import com.atmilan.quartz.model.dto.gb.GbProductResDTO;
import com.atmilan.quartz.model.dto.im.*;
import com.atmilan.quartz.model.dto.im.ImProductPushDTO.SkuList;
import com.atmilan.quartz.model.dto.im.ImProductResDTO.ImProductDTO;
import com.atmilan.quartz.model.dto.jky.JkyProductResDTO;
import com.atmilan.quartz.model.dto.jky.JkyProductResDTO.Goods;
import com.atmilan.quartz.model.dto.jky.JkyProductSkuPriceResDTO;
import com.atmilan.quartz.model.dto.jky.JkyProductSkuResDTO;
import com.atmilan.quartz.model.dto.jky.JkyProductSkuResDTO.GoodsStockQuantity;
import com.atmilan.quartz.model.dto.lavita.LavitaProductResDTO;
import com.atmilan.quartz.model.dto.lavita.LavitaProductSkuRes;
import com.atmilan.quartz.model.dto.lavita.LavitaProductSkuResDTO;
import com.atmilan.quartz.model.dto.lavita.LavitaProductStockRes;
import com.atmilan.quartz.model.dto.leam.LeamProductResDTO;
import com.atmilan.quartz.model.dto.orange.OrangeProductResDTO;
import com.atmilan.quartz.model.dto.pure.PureProductResDTO;
import com.atmilan.quartz.model.dto.pure.PureStockResDTO;
import com.atmilan.quartz.model.dto.vietti.ViettiProductResDTO;
import com.atmilan.quartz.model.dto.vietti.ViettiProductSkuRes;
import com.atmilan.quartz.model.dto.vietti.ViettiProductSkuResDTO;
import com.atmilan.quartz.model.dto.xyy.XyyProductResDTO;
import com.atmilan.quartz.model.dto.xyy.XyyProductSkuResDTO;
import com.atmilan.quartz.model.entity.crmeb.*;
import com.atmilan.quartz.model.entity.europe.EuropeProduct;
import com.atmilan.quartz.model.entity.europe.EuropeProductSku;
import com.atmilan.quartz.model.entity.europe.EuropeProductSkuMerged;
import com.atmilan.quartz.model.entity.pure.PureImages;
import com.atmilan.quartz.model.request.*;
import com.atmilan.quartz.model.request.JackyunGoodsStockInRequest.StockInDetailView;
import com.atmilan.quartz.model.request.JackyunGoodsStockOutRequest.StockOutDetailView;
import com.atmilan.quartz.service.*;
import com.atmilan.quartz.utils.jackyun.BaseRequestBizData;
import com.atmilan.quartz.utils.jackyun.JackyunOpenHttpUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.xml.sax.InputSource;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 远程商品查询相关操作
 * @Description:
 * @author daigb
 * @date 2021-03-12
 */
@Slf4j
@Component
public class ProductUtil {
    @Autowired
    RestTemplateUtil restTemplateUtil;
    @Autowired
    RestTemplateConfig restTemplateConfig;
    @Autowired
    EuropeUtil europeUtil;
    @Autowired
    ISystemConfigService systemConfigService;
    @Autowired
    IJkyContrastService jkyContrastService;
    @Autowired
    IProductImageService productImageService;
    @Autowired
    IStoreProductDescriptionService storeProductDescriptionService;
    @Autowired
    @Lazy
    private IStoreProductMerService storeProductMerService;

    /********* buyer配置参数 *********/
    @Value("${buyer.url}")
    private String buyUrl;
    @Value("${buyer.appkey}")
    private String buyAppKey;
    @Value("${buyer.appsecret}")
    private String buyAppSecret;

    /********* europe配置参数  *********/
    @Value("${europe.url}")
    private String europeUrl;
    @Value("${europe.username}")
    private String europeUsername;
    @Value("${europe.password}")
    private String europePassword;
    private final String xmlGetGoodsById = "<tem:GetGoodsByGoodsID><tem:GoodsID>{}</tem:GoodsID></tem:GetGoodsByGoodsID>";
    private final String xmlGetGoodsDetailByGoodsID = "<tem:GetGoodsDetailByGoodsID><tem:GoodsID>{}</tem:GoodsID></tem:GetGoodsDetailByGoodsID>";
    private final String xmlGoodsPage = "<tem:GetGoodsListByPage><tem:PageNum>{}</tem:PageNum><tem:PageSize>{}</tem:PageSize></tem:GetGoodsListByPage>";

    /********* im配置参数  *********/
    @Value("${im.appKey}")
    private String imAppKey;
    @Value("${im.appSecret}")
    private String imAppSecret;
    @Value("${im.url.domain}")
    private String imDomainUrl;
    @Value("${im.url.goods}")
    private String imGoodsUrl;
    @Value("${im.url.iterationGoods}")
    private String iterationGoodsUrl;
    @Value("${im.url.token}")
    private String imTokenUrl;
    @Value("${im.url.skus}")
    private String imSkusUrl;
    @Value("${im.url.productSkus}")
    private String imProductSkusUrl;
    @Value("${im.url.category}")
    private String imCategoryUrl;
    @Value("${im.url.brand}")
    private String imBrandUrl;
    
    /********* IM反推配置  *********/
    @Value("${imPush.token}")
    private String imPushToken;
    @Value("${imPush.url.domain}")
    private String imPushDomain;
    @Value("${imPush.url.updateProduct}")
    private String imPushUpdateProduct;
    @Value("${imPush.url.updateStock}")
    private String imPushUpdateStock;
    @Value("${imPush.url.productBatch}")
    private String imPushProductBatch;
    @Value("${imPush.url.productEndBatch}")
    private String imPushProductEndBatch;
    @Value("${imPush.url.fullUpdateProduct}")
    private String imPushFullUpdateProduct;

    /********* xyy配置参数  *********/
    @Value("${xyy.appKey}")
    private String xyyAppKey;
    @Value("${xyy.appSecret}")
    private String xyyAppSecret;
    @Value("${xyy.url}")
    private String xyyUrl;

    /********* leam配置参数  *********/
    @Value("${leam.url}")
    private String leamUrl;
    @Value("${leam.token}")
    private String leamToken;

    /********* vietti配置参数  *********/
    @Value("${vietti.client}")
    private String viettiClient;
    @Value("${vietti.appSecret}")
    private String viettiAppSecret;
    @Value("${vietti.appkey}")
    private String viettiAppKey;
    @Value("${vietti.url.domain}")
    private String viettiDomian;
    @Value("${vietti.url.products}")
    private String viettiProducts;
    @Value("${vietti.url.stocks}")
    private String viettiStocks;

    /********* lavita配置参数  *********/
    @Value("${lavita.appid}")
    private String lavitaAppid;
    @Value("${lavita.appsecret}")
    private String lavitaAppsecret;
    @Value("${lavita.url.domain}")
    private String lavitaDomian;
    @Value("${lavita.url.products}")
    private String lavitaProducts;
    @Value("${lavita.url.productInfo}")
    private String productInfo;
    @Value("${lavita.url.stocks}")
    private String lavitaStocks;

    /********* coltorti配置参数  *********/
    @Value("${coltorti.username}")
    private String coltortiUsername;
    @Value("${coltorti.password}")
    private String coltortiPassword;
    @Value("${coltorti.url}")
    private String coltortiUrl;

    /********* bellettini配置参数  *********/
    @Value("${bellettini.url}")
    private String bellettiniUrl;
    @Value("${bellettini.key}")
    private String bellettiniKey;
    @Value("${bellettini.type}")
    private String bellettiniType;

    /********* gb配置参数  *********/
    @Value("${gb.hostName}")
    private String gbHostName;
    @Value("${gb.userName}")
    private String gbUserName;
    @Value("${gb.password}")
    private String gbPassword;

    /********* carotta配置参数  *********/
    @Value("${carotta.url}")
    private String carottaUrl;
    @Value("${carotta.key}")
    private String carottaKey;
    @Value("${carotta.password}")
    private String carottaPassword;
    @Value("${carotta.version}")
    private String carottaVersion;

    /********* folli配置参数  *********/
    @Value("${folli.url}")
    private String folliUrl;
    @Value("${folli.key}")
    private String folliKey;
    @Value("${folli.company}")
    private String folliCompany;

    /********* delloglio配置参数  *********/
    @Value("${delloglio.url}")
    private String delloglioUrl;

    /********* orange配置参数  *********/
    @Value("${orange.url}")
    private String orangeUrl;
    @Value("${orange.appId}")
    private String orangeAppId;
    @Value("${orange.secret}")
    private String orangeSecret;

    /********* pure配置参数  *********/
    @Value("${pure.url}")
    private String pureUrl;
    @Value("${pure.products}")
    private String pureProducts;
    @Value("${pure.stocks}")
    private String pureStocks;
    
    @Value("${aliyun.oss.oss-url}")
    private String ossUrl;

    String url = "";
    String appId = "";
    /** 开发者私钥 */
    String privateKeyIsv = "";
    /** 开放平台提供的公钥
     * 前往SOP-ADMIN，ISV管理--秘钥管理，生成平台提供的公私钥，然后把【平台公钥】放到这里 */
    String publicKeyPlatform = "";

    /**
     * 获取商品实时库存
     * @Description:  
     * @author daigb 
     * @param @param barCode 源商品goodsId
     * @param @param color 颜色(欧洲可为空,buyer必传)
     * @param @param size 尺码
     * @param @return
     * @return Integer
     * @throws
     */
    public Integer getStockByBarCode(String barCode, String color, String size) {
        try {
			if (StringUtil.isEmpty(barCode) || 4 >= barCode.length()) {
			    return 0;
			}
			String id = barCode.substring(0, 4);

			// buyer商品
			if (BarCodeEnum.BUYER == BarCodeEnum.valueOf(Integer.parseInt(id))) {
			    return this.getBuyerStockByBarCode(barCode, color, size);
			    // 欧洲商品
			} else if (BarCodeEnum.EUROPE == BarCodeEnum.valueOf(Integer.parseInt(id))) {
			    return getEuropeStockByBarCode(barCode, size);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

        return 0;
    }

    /******************* buyer ********************/
    /**
     * 获取buyer商品数据和详情
     * @Description:  
     * @author daigb 
     * @param @param id 商品barCode
     * @param @return
     * @param @throws Exception
     * @return BuyerProductResDTO
     * @throws
     */
    public BuyerProductResDTO getBuyerProductByBarCode(String barCode) throws Exception {
        BuyerProductResDTO buyerProductResDTO = null;
		try {
			if (StringUtil.isEmpty(barCode) || 4 >= barCode.length()) {
			    return null;
			}
			String id = barCode.substring(4, barCode.length());

			// log.info("--------------- 查询buyer远程数据, 商品id: {} ---------------", id);
			String timestamp = String.valueOf(Instant.now().getEpochSecond());
			String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
			String signature = getSignature(timestamp, random);
			Map<String, String> parMap = new HashMap<String, String>();
			parMap.put("appkey", this.buyAppKey);
			parMap.put("appsecret", this.buyAppSecret);
			parMap.put("t", timestamp);
			parMap.put("r", random);
			parMap.put("s", signature);
			parMap.put("op", "goods");
			parMap.put("action", "list");
			parMap.put("goods_ids", id);
			String result = restTemplateUtil.getData(this.buyUrl + "?appkey={appkey}&appsecret={appsecret}&t={t}&r={r}&s={s}&op={op}&action={action}&goods_ids={goods_ids}", parMap);
			// log.info("--------------- buyer远程数据返回结果: {} ---------------", result);

			ObjectMapper mapper = new ObjectMapper();
			buyerProductResDTO = mapper.readValue(result, BuyerProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return buyerProductResDTO;
    }

    /**
     * 获取buyer商品列表
     * @Description:  
     * @author daigb 
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return BuyerProductResDTO
     * @throws
     */
    public BuyerProductResDTO selectBuyerPage(Integer pageNow, Integer pageSize) throws Exception {
        BuyerProductResDTO buyerProductResDTO = null;
		try {
			String timestamp = String.valueOf(Instant.now().getEpochSecond());
			String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
			String signature = getSignature(timestamp, random);
			Map<String, String> parMap = new HashMap<String, String>();
			parMap.put("appkey", this.buyAppKey);
			parMap.put("appsecret", this.buyAppSecret);
			parMap.put("t", timestamp);
			parMap.put("r", random);
			parMap.put("s", signature);
			parMap.put("op", "goods");
			parMap.put("action", "list");
			parMap.put("p", pageNow + "");
			parMap.put("n", pageSize + "");
			parMap.put("stock", "1");
			String result = restTemplateUtil.getData(this.buyUrl + "?appkey={appkey}&appsecret={appsecret}&t={t}&r={r}&s={s}&op={op}&action={action}&p={p}&n={n}&stock={stock}", parMap);

			ObjectMapper mapper = new ObjectMapper();
			buyerProductResDTO = mapper.readValue(result, BuyerProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return buyerProductResDTO;
    }

    // Buyer商品库存计算
    private Integer getBuyerStockByBarCode(String barCode, String color, String size) {
        int stock = 0;
        try {
            BuyerProductResDTO buyerProductResDTO = getBuyerProductByBarCode(barCode);
            if (null == buyerProductResDTO || StringUtil.isEmpty(color) || StringUtil.isEmpty(size)) {
                log.info("--------------- 查询buyer远程数据, 商品为空: {} 或参数缺失, color:{}, size: {} ---------------", null == buyerProductResDTO, color, size);
                return stock;
            }
            List<Product> products = buyerProductResDTO.getProduct();
            if (CollectionUtils.isEmpty(products)) {
                log.info("--------------- 查询buyer远程数据, products为空, barCode:{}  ---------------", barCode);
                return stock;
            }
            List<ProductSku> productSkus = products.get(0).getSkus();
            if (CollectionUtils.isEmpty(productSkus)) {
                log.info("--------------- 查询buyer远程数据, productSkus为空, barCode:{}  ---------------", barCode);
                return stock;
            }
            ProductSku productSku = productSkus.stream().filter(obj -> obj.getColor().equals(color) && obj.getSize().equals(size)).findFirst().orElse(null);

            return null == productSku ? stock : productSku.getStock();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return stock;
    }

    /******************* end ********************/

    /******************* eur ********************/
    /**
     * 获取远程Europe商品和详情
     * @Description:  
     * @author daigb 
     * @param @param barCode
     * @param @return
     * @return EuropeProduct
     * @throws
     */
    public EuropeProduct getEuropeByBarCode(String barCode) {
        if (StringUtil.isEmpty(barCode) || 4 >= barCode.length()) {
            return null;
        }
        String id = barCode.substring(4, barCode.length());

        try {
            log.info("--------------- 查询Europe商品远程数据, 商品id: {} ---------------", id);
            String auth = Base64.encode((europeUsername + ":" + europePassword).getBytes());
            String msg = EuropeUtil.getSendMsg(StrUtil.format(xmlGetGoodsById, id));
            String respXml = europeUtil.getEuropeXmlNew(auth, europeUrl, msg);
            log.info("--------------- 获取到Europe商品远程数据, 报文为: {} ---------------", respXml);
            if (StringUtil.isEmpty(respXml)) {
                log.info("--------------- 获取到Europe商品远程数据, respXml数据为空:{} ---------------", id);
                return null;
            }
            // 数据提取(获取单个商品数据)
            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsByGoodsID");
            if (CollectionUtils.isEmpty(europMapList)) {
                log.info("--------------- 获取到Europe商品远程数据, europMapList数据为空:{} ---------------", id);
                return null;
            }
            // 解析主商品
            Map<String, Object> europMap = europMapList.get(0);
            BigDecimal price = new BigDecimal((String) europMap.get("Price"));
            String goodsId = (String) europMap.get("ID");
            EuropeProduct europeGood = new EuropeProduct();
            // 解析商品sku
            List<EuropeProductSku> productSkus = getEuropeProductSkus(goodsId);
            europeGood = getEuropeProduct(europeGood, europMap, price, productSkus);
            // 解析商品skuMerged
            Map<String, Integer> sumStockMap = productSkus.stream().collect(Collectors.groupingBy(c -> c.getAttrKey(), Collectors.summingInt(EuropeProductSku::getQty)));
            productSkus = productSkus.stream().filter(sku -> StringUtil.isNotEmpty(sku.getAttrKey() + sku.getSize())).map(sku -> sku.setQty(sumStockMap.get(sku.getAttrKey()))).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(EuropeProductSku::getAttrKey))), ArrayList::new));
            europeGood.setSkuList(productSkus);
            List<EuropeProductSkuMerged> europeProductSkuMergeds = new ArrayList<EuropeProductSkuMerged>();
            productSkus.forEach(sku -> {
                if (0 < sku.getQty()) {
                    EuropeProductSkuMerged skuMerged = new EuropeProductSkuMerged();
                    skuMerged.setSkuId(sku.getId());
                    skuMerged.setGoodsId(sku.getGoodsId() + "");
                    skuMerged.setStock(sku.getQty());
                    skuMerged.setColor(sku.getColor());
                    skuMerged.setSize(sku.getSize());
                    skuMerged.setUpdateFlag(sku.getUpdateFlag());
                    skuMerged.setCreateTime(sku.getNewCreatedTime());
                    skuMerged.setEditTime(sku.getNewModifyTime());
                    skuMerged.setSuk(sku.getSuk());
                    skuMerged.setCreateTime(new Date());
                    europeProductSkuMergeds.add(skuMerged);
                }
            });

            europeGood.setSkuMergedList(europeProductSkuMergeds);
            return europeGood;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取远程Europe商品分页列表
     * @Description:  
     * @author daigb 
     * @param @param barCode
     * @param @return
     * @return EuropeProduct
     * @throws
     */
    public List<EuropeProduct> selectEuropePage(Integer pageNo, Integer pageSize) {
        List<EuropeProduct> europeProducts = new ArrayList<>();
        try {
            String auth = Base64.encode((europeUsername + ":" + europePassword).getBytes());
            String msg = EuropeUtil.getSendMsg(StrUtil.format(xmlGoodsPage, pageNo, pageSize));
            String respXml = europeUtil.getEuropeXmlNew(auth, europeUrl, msg);
            if (StringUtil.isEmpty(respXml)) {
                return europeProducts;
            }
            // 数据提取
            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsListByPage");
            if (CollectionUtils.isEmpty(europMapList)) {
                log.info("--------------- Europe商品抓取结束, pageNo: {}, pageSize: {}  ---------------", pageNo, europeProducts.size());
                return null;
            }
            // 解析主商品
            for (Map<String, Object> europMap : europMapList) {
                BigDecimal price = new BigDecimal((String) europMap.get("Price"));
                String goodsId = (String) europMap.get("ID");
                String stock = (String) europMap.get("Stock");
                // 价格或库存非法
                if (0 >= Integer.parseInt(stock) || -1 < BigDecimal.ZERO.compareTo(price)) {
                    continue;
                }
                EuropeProduct europeGood = new EuropeProduct();
                // 解析商品sku
                List<EuropeProductSku> productSkus = getEuropeProductSkus(goodsId);
                europeGood = getEuropeProduct(europeGood, europMap, price, productSkus);
                // 解析商品skuMerged
                Map<String, Integer> sumStockMap = productSkus.stream().collect(Collectors.groupingBy(c -> c.getAttrKey(), Collectors.summingInt(EuropeProductSku::getQty)));
                productSkus = productSkus.stream().filter(sku -> StringUtil.isNotEmpty(sku.getAttrKey() + sku.getSize())).map(sku -> sku.setQty(sumStockMap.get(sku.getAttrKey()))).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(EuropeProductSku::getAttrKey))), ArrayList::new));
                europeGood.setSkuList(productSkus);
                List<EuropeProductSkuMerged> europeProductSkuMergeds = new ArrayList<EuropeProductSkuMerged>();
                productSkus.forEach(sku -> {
                    if (0 < sku.getQty()) {
                        EuropeProductSkuMerged skuMerged = new EuropeProductSkuMerged();
                        skuMerged.setSkuId(sku.getId());
                        skuMerged.setGoodsId(sku.getGoodsId() + "");
                        skuMerged.setStock(sku.getQty());
                        skuMerged.setColor(sku.getColor());
                        skuMerged.setSize(sku.getSize());
                        skuMerged.setUpdateFlag(sku.getUpdateFlag());
                        skuMerged.setCreateTime(sku.getNewCreatedTime());
                        skuMerged.setEditTime(sku.getNewModifyTime());
                        skuMerged.setSuk(sku.getSuk());
                        skuMerged.setCreateTime(new Date());
                        europeProductSkuMergeds.add(skuMerged);
                    }
                });

                europeGood.setSkuMergedList(europeProductSkuMergeds);
                europeProducts.add(europeGood);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return europeProducts;
    }

    /**
     * 获得Europe商品详情
     * @Description:  
     * @author daigb 
     * @param @param goodsId
     * @param @return
     * @return List<EuropeProductSku>
     * @throws
     */
    public List<EuropeProductSku> getEuropeProductSkus(String goodsId) {
    	try {
	        String auth = Base64.encode((europeUsername + ":" + europePassword).getBytes());
	        String sendMsg = EuropeUtil.getSendMsg(StrUtil.format(xmlGetGoodsDetailByGoodsID, goodsId));
            String respXml = europeUtil.getEuropeXmlNew(auth, europeUrl, sendMsg);
            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsDetailByGoodsID");

            Map<String, Object> map = europMapList.get(0);
            List<EuropeProductSku> list = new ArrayList<>();
            @SuppressWarnings("unchecked")
            List<HashMap<String, Object>> stockList = (List<HashMap<String, Object>>) map.get("Stock");

            stockList.forEach(item -> {
                EuropeProductSku europeProductSku = new EuropeProductSku();
                int qty = Integer.parseInt((String) item.get("Qty"));
                getEuropeProductSku(qty, europeProductSku, map, item, stockList);
                list.add(europeProductSku);
            });
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    // Europe商品构建
    private EuropeProduct getEuropeProduct(EuropeProduct europeGood, Map<String, Object> map, BigDecimal price, List<EuropeProductSku> productSkus) {
        try {
			europeGood.setGoodId(Integer.parseInt((String) map.get("ID")));
			europeGood.setModel((String) map.get("Model"));
			europeGood.setVariante((String) map.get("Variante"));
			europeGood.setSeason((String) map.get("Season"));
			europeGood.setCollection((String) map.get("Collection"));
			europeGood.setSupplierId(Integer.parseInt((String) map.get("SupplierID")));
			europeGood.setBrandId(Integer.parseInt((String) map.get("BrandID")));
			europeGood.setParentCategoryId(Integer.parseInt((String) map.get("ParentCategoryID")));
			europeGood.setCategoryId(Integer.parseInt((String) map.get("CategoryID")));
			europeGood.setTypeId(Integer.parseInt((String) map.get("TypeID")));
			europeGood.setCode((String) map.get("Code"));
			europeGood.setGoodsName((String) map.get("GoodsName"));
			europeGood.setReferencePrice(new BigDecimal((String) map.get("ReferencePrice")));
			europeGood.setPrice(price);
			europeGood.setDiscount((String) map.get("Discount"));
			europeGood.setStock(Integer.parseInt((String) map.get("Stock")));
			europeGood.setMainPicNo((String) map.get("MainPicNo"));
			europeGood.setNewModifyTime(DateUtil.date());
			europeGood.setNewCreatedTime(DateUtil.date());
			//获取商品sku的缩略图和商品相册
			if (productSkus != null && productSkus.size() > 0) {
			    if (StringUtil.isNotEmpty(productSkus.get(0).getPictures())) {
			        @SuppressWarnings("rawtypes")
			        List<Map> lists = JSONObject.parseArray(productSkus.get(0).getPictures(), Map.class);
			        List<Map<String, Object>> list = new ArrayList<>();
			        lists.forEach(vo -> {
			            Map<String, Object> map1 = new HashMap<>();
			            map1.put("img_original", (String) vo.get("PictureUrl"));
			            map1.put("thumb_url", vo.get("PictureThumbUrl"));
			            list.add(map1);
			        });
			        europeGood.setGallery(JSONObject.toJSONString(list));
			        if (!CollectionUtils.isEmpty(lists)) {
			            europeGood.setGoodsImg((String) lists.get(0).get("PictureUrl"));
			        }
			    } else {
			        europeGood.setGallery("");
			        europeGood.setGoodsImg("");
			    }
			} else {
			    europeGood.setGallery("");
			    europeGood.setGoodsImg("");
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}

        try {
            String oldCreatedTime = (String) map.get("CreatedTime");
            if (oldCreatedTime != null && StringUtil.isNotEmpty(oldCreatedTime)) {
                if (oldCreatedTime.endsWith("AM")) {
                    oldCreatedTime = oldCreatedTime.replace(" AM", "");
                    europeGood.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                } else {
                    oldCreatedTime = oldCreatedTime.replace(" PM", "");
                    europeGood.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                }
            } else {
                europeGood.setOldCreatedTime(null);
            }
            String oldModifyTime = (String) map.get("ModifyTime");
            if (oldModifyTime != null && StringUtil.isNotEmpty(oldModifyTime)) {
                if (oldModifyTime.endsWith("AM")) {
                    oldModifyTime = oldModifyTime.replace(" AM", "");
                    europeGood.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } else {
                    oldModifyTime = oldModifyTime.replace(" PM", "");
                    europeGood.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                }
            } else {
                europeGood.setOldModifyTime(null);
            }
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return europeGood;
    }

    // Europe商品sku获取
    private EuropeProductSku getEuropeProductSku(int qty, EuropeProductSku europeProductSku, Map<String, Object> map, HashMap<String, Object> item, List<HashMap<String, Object>> stockList) {
    	try {
	    	europeProductSku.setId((String) map.get("ID") + "-" + item.get("Size"));
	        europeProductSku.setGoodsId(Integer.parseInt((String) map.get("ID")));
	        europeProductSku.setSuperColor((String) map.get("SuperColor"));
	        europeProductSku.setColor((String) map.get("Color"));
	        europeProductSku.setFabric((String) map.get("Fabric"));
	        europeProductSku.setComposition((String) map.get("Composition"));
	        europeProductSku.setSizeAndFit((String) map.get("SizeAndFit"));
	        europeProductSku.setMadeIn((String) map.get("MadeIn"));

	        if (StringUtil.isNotEmpty(map.get("Pictures").toString())) {
	            @SuppressWarnings("unchecked")
	            List<HashMap<String, Object>> pictures = (List<HashMap<String, Object>>) map.get("Pictures");
	            europeProductSku.setPictures(JSONObject.toJSONString(pictures));
	        }
	        if (StringUtil.isNotEmpty(map.get("Stock").toString())) {
	            @SuppressWarnings("unchecked")
	            List<HashMap<String, Object>> stock = (List<HashMap<String, Object>>) map.get("Stock");
	            europeProductSku.setStock(JSONObject.toJSONString(stock));
	        }
	        europeProductSku.setSize((String) item.get("Size"));
	        europeProductSku.setQty(qty);
	        europeProductSku.setSuk((String) map.get("Color") + "," + (String) item.get("Size"));
	        String oldCreatedTime = (String) map.get("CreatedTime");
            if (oldCreatedTime != null && StringUtil.isNotEmpty(oldCreatedTime)) {
                if (oldCreatedTime.endsWith("AM")) {
                    oldCreatedTime = oldCreatedTime.replace(" AM", "");
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));
                } else {
                    oldCreatedTime = oldCreatedTime.replace(" PM", "");
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));
                }
            } else {
                europeProductSku.setOldCreatedTime(null);
            }
            String oldModifyTime = (String) map.get("ModifyTime");
            if (oldModifyTime != null && StringUtil.isNotEmpty(oldModifyTime)) {
                if (oldModifyTime.endsWith("AM")) {
                    oldModifyTime = oldModifyTime.replace(" AM", "");
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } else {
                    oldModifyTime = oldModifyTime.replace(" PM", "");
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                }
            } else {
                europeProductSku.setOldModifyTime(null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return europeProductSku;
    }

    // 签名
    private String getSignature(String timestamp, String random) {
        String signStr = null;
		try {
			Map<String, String> signMap = MapUtil.newHashMap(4);
			signMap.put("timeStamp", timestamp);
			signMap.put("randomStr", random);
			signMap.put("appkey", this.buyAppKey);
			signMap.put("appsecret", this.buyAppSecret);

			List<String> valueList = signMap.entrySet().stream().sorted(Map.Entry.comparingByValue()).map(Map.Entry::getValue).collect(Collectors.toList());
			signStr = String.join("", valueList);
			signStr = DigestUtil.sha1Hex(signStr);
			signStr = DigestUtil.md5Hex(signStr);
			signStr = DigestUtil.md5Hex(signStr);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return signStr.toUpperCase();
    }

    // Europe商品库存计算
    private Integer getEuropeStockByBarCode(String barCode, String size) {
        int stock = 0;
        try {
            if (StringUtil.isEmpty(barCode) || 4 >= barCode.length()) {
                return stock;
            }
            String id = barCode.substring(4, barCode.length());

            List<EuropeProductSku> EuropeProductSkus = this.getEuropeProductSkus(id);
            if (CollectionUtils.isEmpty(EuropeProductSkus) || StringUtil.isEmpty(size)) {
                log.info("--------------- 查询Europe远程数据, 商品规格为空: {} 或参数缺失, size: {} ---------------", CollectionUtils.isEmpty(EuropeProductSkus), size);
                return stock;
            }
            EuropeProductSku productSku = EuropeProductSkus.stream().filter(obj -> obj.getSize().equals(size)).findFirst().orElse(null);

            return null == productSku ? stock : productSku.getQty();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return stock;
    }

    /******************* end ********************/

    /******************* im ********************/
    /**
     * 查询im分页商品数据
     * @Description:  
     * @author daigb 
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public ImProductResDTO selectImPage(Integer pageNow, Integer pageSize, SystemConfig systemConfig) throws Exception {
        ImProductResDTO imProductResDTO = null;
		try {
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("access-token", systemConfig.getValue());
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("cursorId", pageNow);
			param.put("limit", pageSize);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.imGoodsUrl, formEntity, String.class);
			ObjectMapper mapper = new ObjectMapper();
			imProductResDTO = mapper.readValue(response.getBody(), ImProductResDTO.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
//			    String errorMessage = message.getString("error");

			    log.info("---------------im分页商品数据异常: {} ---------------", response);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

        return imProductResDTO;
    }

    /**
     * 获取增量数据
     * @param cursorId
     * @param limit
     * @param systemConfig
     * @return
     * @throws Exception
     */
    public ImProductResDTO selectImChangePage(Integer cursorId, Integer limit, SystemConfig systemConfig, Long fromChangedTime, Long toChangedTime) throws Exception {
    	ImProductResDTO imProductResDTO = null;
		try {
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("access-token", systemConfig.getValue());
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("cursorId", cursorId);
			param.put("limit", limit);
			param.put("fromChangedTime", fromChangedTime);
			param.put("toChangedTime", toChangedTime);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.iterationGoodsUrl, formEntity, String.class);
			ObjectMapper mapper = new ObjectMapper();
			imProductResDTO = mapper.readValue(response.getBody(), ImProductResDTO.class);
			if (HttpStatus.OK != response.getStatusCode()) {
				JSONObject message = JSONObject.parseObject(response.getBody());
//				String errorMessage = message.getString("error");

				log.info("---------------im获取增量数据异常 {} ---------------", message);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

    	return imProductResDTO;
    }

    /**
     * 批量获取im商品sku
     * @Description:  
     * @author daigb 
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public ImProductSkuResDTO getImSkus(List<ImProductDTO> imProducts, SystemConfig systemConfig) throws Exception {
        ImProductSkuResDTO imProductSkuResDTO = null;
		try {
			List<Integer> ids = imProducts.stream().map(ImProductDTO::getProductId).collect(Collectors.toList());

			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("access-token", systemConfig.getValue());
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("productIds", ids);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.imSkusUrl, formEntity, String.class);

			ObjectMapper mapper = new ObjectMapper();
			imProductSkuResDTO = mapper.readValue(response.getBody(), ImProductSkuResDTO.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- 批量获取im商品sku异常: {} ---------------", errorMessage);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

        return imProductSkuResDTO;
    }

    /**
     * 获取发货时间
     * @param tempId 发货地
     * @param isEurope 商品来源
     * @param merId 商户id
     * @param productId 商品id
     * @return 发货时间
     */
    public String getDeliveryTimeByTempId(Integer tempId,Integer isEurope,Integer merId,Integer productId){
        //橙子商品
        if(Objects.equals(isEurope,ProductTypeEnum.ORANGE.getCode())){
            String deliverDays = OrangeChannelTypeEnum.valueOf(tempId).getDeliverDays();
            return "预计"+deliverDays+"个工作日发货";
        }
        //自建商品 自定义收货时间
        if(Objects.equals(isEurope, ProductTypeEnum.INSIDE.getCode())){
            MybatisPlusConfig.tableNameMp.set(TableNameUtil.getProductMerName(merId));
            StoreProductMer mer = storeProductMerService.getOne(Wrappers.<StoreProductMer>lambdaQuery()
                    .eq(StoreProductMer::getProductId, productId)
            );
            return Objects.isNull(mer) ?  "预计2个工作日发货" : "预计"+mer.getDeliveryData()+"个工作日发货";
        }
        return Objects.equals(tempId, StockAreaTempEnum.EUR.getTempId()) ? systemConfigService.getValueByKey(Constants.SYSTEM_CONFIG_EUR_DELIVERY_TIME)
                : systemConfigService.getValueByKey(Constants.SYSTEM_CONFIG_HK_DELIVERY_TIME);
    }

    /**
     * 批量获取improduct商品sku
     * @Description:
     * @author daigb
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public ImProductInfoSkuResDTO getImProductSkus(List<ImProductDTO> imProducts, SystemConfig systemConfig) throws Exception {
    	ImProductInfoSkuResDTO imProductInfoSkuResDTO = null;
		try {
			List<Integer> ids = imProducts.stream().map(ImProductDTO::getProductId).collect(Collectors.toList());

			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("access-token", systemConfig.getValue());
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("productIds", ids);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.imProductSkusUrl, formEntity, String.class);

			ObjectMapper mapper = new ObjectMapper();
			imProductInfoSkuResDTO = mapper.readValue(response.getBody(), ImProductInfoSkuResDTO.class);
			if (HttpStatus.OK != response.getStatusCode()) {
				JSONObject message = JSONObject.parseObject(response.getBody());
				String errorMessage = message.getString("error");

				log.info("--------------- 批量获取improduct商品sku异常: {} ---------------", errorMessage);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

    	return imProductInfoSkuResDTO;
    }

    public ImBrandResDTO getImBrands(List<Integer> brandIds, SystemConfig systemConfig) throws Exception {
        ImBrandResDTO imBrandResDTO = null;
		try {
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("access-token", systemConfig.getValue());
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("brandIds", brandIds);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.imBrandUrl, formEntity, String.class);

			ObjectMapper mapper = new ObjectMapper();
			imBrandResDTO = mapper.readValue(response.getBody(), ImBrandResDTO.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- IM品牌获取失败: {} ---------------", errorMessage);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

        return imBrandResDTO;
    }

    // 获取Im token
    public SystemConfig getImToken(SystemConfig systemConfigParam) {
        try {
			SystemConfig systemConfig = systemConfigService.getOne(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getName, Constants.IM_TOKEN).last("LIMIT 1"));
			// token已被更新
			if (systemConfig.getFormId().intValue() != systemConfigParam.getFormId()) {
				log.info("--------------- IM获取token时发现token已被更新, 直接返回数据库token: {}, {} ---------------", systemConfig.getFormId(), systemConfigParam.getFormId());
			    return systemConfig;
			}

			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("x-forwarded-for", "121.4.132.191");
			JSONObject param = new JSONObject();
			param.put("appKey", this.imAppKey);
			param.put("appSecret", this.imAppSecret);
			HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(this.imDomainUrl + this.imTokenUrl, formEntity, String.class);

			log.info("--------------- IM授权获取token返回: {} ---------------", response);
			if (HttpStatus.OK == response.getStatusCode()) {
			    String token = JSONObject.parseObject(response.getBody()).getJSONObject("data").getString("access_token");
			    systemConfigParam.setValue(token);
			    systemConfigParam.setFormId(systemConfigParam.getFormId() + 1);
			    systemConfigParam.setUpdateTime(new Date());
			    systemConfigService.updateById(systemConfigParam);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

        return systemConfigParam;
    }

    /******************* end ********************/

    /******************* IM反向推送商品相关接口 ********************/
    
    /**
     * 更新IM商品
     * @Description:  
     * @author daigb 
     * @param @param goodsNo
     * @param @param skuBarcode
     * @param @throws Exception
     * @return void
     * @throws
     */
    public void updateImPushGoods(StoreProduct product, List<StoreProductAttrValue> values, CategoryMatch category1, CategoryMatch category2, CategoryMatch category3) throws Exception {
        // 轮播图
        try {
			// sku信息, 通过色号拆分商品
        	Map<String, List<SkuList>> skuColors = new HashMap<>();
			for(StoreProductAttrValue value : values) {
			    String[] suks = value.getSuk().split(",");
			    String color = suks.length > 1 ? suks[1].split(";")[0] : "";

			    SkuList sku = new SkuList();
			    sku.setRetailPrice(value.getOtPrice().multiply(new BigDecimal("8")));
			    sku.setSize(suks.length > 1 ? suks[1] : suks[0]);
			    sku.setStock(value.getStock());
			    sku.setBarcode(value.getSourceSkuId());
			    sku.setCostPrice(value.getCost());
			    sku.setSupplyPrice(value.getPrice());
			    
			    List<SkuList> skuList = skuColors.get(color);
			    if(null == skuList) {
			    	skuList = new ArrayList<>();
			    	skuList.add(sku);
			    	skuColors.put(color, skuList);
			    } else {
			    	skuList.add(sku);
			    }
			}

			for(Map.Entry<String, List<SkuList>> m : skuColors.entrySet()) {
				String color = m.getKey();
			    List<SkuList> skuList = m.getValue();
			    // 获取色号对应图片
				List<ProductImage> images = productImageService.list(Wrappers.<ProductImage>lambdaQuery()
	                    .eq(ProductImage :: getFolderName, product.getKeyword())
	                    .in(ProductImage :: getColor, color)
	                    .notIn(ProductImage :: getType, Arrays.asList("SP2", "SP3"))
	                    .orderByAsc(ProductImage :: getTypeSort, ProductImage :: getColor, ProductImage :: getSort)
	                    );
			    List<String> strImages = images.stream().map(obj -> ossUrl + Constants.UPLOAD_FILE_WAREHOUSE_DIR + obj.getUrl()).collect(Collectors.toList());
				
			    ImProductPushDTO imProductPushDTO = new ImProductPushDTO();
			    imProductPushDTO.setBoutiqueId(product.getBarCode() + "-" + color);
			    imProductPushDTO.setColorCode(color);
			    imProductPushDTO.setDesignerId(product.getKeyword());
			    imProductPushDTO.setBrandName(product.getBrandName());
			    imProductPushDTO.setCategory1(null != category1 ? category1.getName() : "");
			    imProductPushDTO.setCategory2(null != category2 ? category2.getName() : "");
			    imProductPushDTO.setCategory3(null != category3 ? category3.getName() : "");
			    imProductPushDTO.setComposition(product.getComposition());
			    imProductPushDTO.setImages(strImages);
			    imProductPushDTO.setProductDescription(product.getStoreInfo());
			    imProductPushDTO.setProductName(product.getStoreName());
			    imProductPushDTO.setSeasonCode(StringUtil.isEmpty(product.getSeasonCode()) ? "carryover" : product.getSeasonCode());
			    imProductPushDTO.setSkuList(skuList);
			    
			    
			    RestTemplate restTemplate = restTemplateConfig.restTemplate();
			    HttpHeaders headers = new HttpHeaders();
			    headers.setContentType(MediaType.APPLICATION_JSON);
			    headers.add("Auth-Token", imPushToken);
			    JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(imProductPushDTO));
			    HttpEntity<JSONObject> formEntity = new HttpEntity<>(json, headers);
			    ResponseEntity<String> response = restTemplate.postForEntity(imPushDomain + imPushUpdateProduct, formEntity, String.class);
			    
			    if (HttpStatus.OK != response.getStatusCode()) {
			    	JSONObject message = JSONObject.parseObject(response.getBody());
			    	String errorMessage = message.getString("error");
			    	
			    	log.info("--------------- IM商品: {} 推送异常: {} ---------------", json, errorMessage);
			    }
			    Boolean b = JSONObject.parseObject(response.getBody()).getBoolean("success");
			    if(!b) {
			    	log.info("--------------- IM商品推送失败---------------", json);
			    }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    /**
     * 构建待推送商品数据
     * @author daigb
     * @date:  2022-04-01 15:20
     */
    public List<ImProductPushDTO> createImGoods(StoreProduct product, List<StoreProductAttrValue> values, CategoryMatch category1, CategoryMatch category2, CategoryMatch category3) throws Exception {
    	// 轮播图
    	try {
    		// sku信息, 通过色号拆分商品
    		Map<String, List<SkuList>> skuColors = new HashMap<>();
    		for(StoreProductAttrValue value : values) {
    			String[] suks = value.getSuk().split(",");
    			String color = "";
    			String size = suks[0];
    			if(suks.length > 1) {
    				String[] suk = suks[1].split(";");
    				color = suk[0];
    				size = suk.length > 1 ? suk[1].split("=")[0] : suk[0].split("=")[0];
    			}
    			
    			SkuList sku = new SkuList();
    			sku.setRetailPrice(value.getOtPrice().multiply(new BigDecimal("8")));
    			sku.setSize(size);
    			sku.setStock(value.getStock());
    			sku.setBarcode(value.getSourceSkuId());
    			sku.setCostPrice(value.getCost());
    			sku.setSupplyPrice(value.getPrice());
    			
    			List<SkuList> skuList = skuColors.get(color);
    			if(null == skuList) {
    				skuList = new ArrayList<>();
    				skuList.add(sku);
    				skuColors.put(color, skuList);
    			} else {
    				skuList.add(sku);
    			}
    		}
    		
    		List<ImProductPushDTO> productDTOs = new ArrayList<>();
    		for(Map.Entry<String, List<SkuList>> m : skuColors.entrySet()) {
    			String color = m.getKey();
    			List<SkuList> skuList = m.getValue();
    			// 获取色号对应图片
				List<ProductImage> images = productImageService.list(Wrappers.<ProductImage>lambdaQuery()
	                    .eq(ProductImage :: getFolderName, product.getKeyword())
	                    .in(ProductImage :: getColor, color)
	                    .notIn(ProductImage :: getType, Arrays.asList("SP2", "SP3"))
	                    .orderByAsc(ProductImage :: getTypeSort, ProductImage :: getColor, ProductImage :: getSort)
	                    );
			    List<String> strImages = images.stream().map(obj -> ossUrl + Constants.UPLOAD_FILE_WAREHOUSE_DIR + obj.getUrl()).collect(Collectors.toList());
    			
    			ImProductPushDTO imProductPushDTO = new ImProductPushDTO();
    			imProductPushDTO.setBoutiqueId(product.getBarCode() + "-" + color);
    			imProductPushDTO.setColorCode(color);
    			imProductPushDTO.setSizeCountry("IT");
    			imProductPushDTO.setMadeIn("IT");
    			imProductPushDTO.setDesignerId(product.getKeyword());
    			imProductPushDTO.setBrandName(product.getBrandName());
    			imProductPushDTO.setCategory1(null != category1 ? category1.getName() : "");
    			imProductPushDTO.setCategory2(null != category2 ? category2.getName() : "");
    			imProductPushDTO.setCategory3(null != category3 ? category3.getName() : "");
    			imProductPushDTO.setComposition(product.getComposition());
    			imProductPushDTO.setImages(strImages);
    			imProductPushDTO.setProductDescription(product.getStoreInfo());
    			imProductPushDTO.setProductName(product.getStoreName());
    			imProductPushDTO.setSeasonCode(StringUtil.isEmpty(product.getSeasonCode()) ? "carryover" : product.getSeasonCode());
    			imProductPushDTO.setSkuList(skuList);
    			
    			productDTOs.add(imProductPushDTO);
    		}
    		
    		return productDTOs;
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	
    	return null;
    }
    
    /**
     * 批次更新商品
     * @author daigb
     * @date:  2022-04-01 15:11
     */
    public void batchUpdateImGoods(List<ImProductPushDTO> imProducts, String batchId) throws Exception {
    	try {
    		RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.add("Auth-Token", imPushToken);
			JSONArray json = JSONArray.parseArray(JSONArray.toJSONString(imProducts));
			HttpEntity<JSONArray> formEntity = new HttpEntity<>(json, headers);
			ResponseEntity<String> response = restTemplate.postForEntity(imPushDomain + imPushFullUpdateProduct + "?batchId=" + batchId, formEntity, String.class);
			
			if (HttpStatus.OK != response.getStatusCode()) {
				JSONObject message = JSONObject.parseObject(response.getBody());
				String errorMessage = message.getString("message");
				
				log.info("--------------- IM商品 批量推送异常: {} ---------------", errorMessage);
			}
			Boolean b = JSONObject.parseObject(response.getBody()).getBoolean("success");
			if(!b) {
				log.info("--------------- IM商品批量推送失败: {}---------------", response);
			}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    
    /**
     * 通过barcode更新指定商品库存
     * @author daigb
     * @date:  2022-03-31 16:21
     */
    public void updateImStock(StoreProduct product, List<StoreProductAttrValue> values) {
    	// 轮播图
        try {
			// sku信息, 通过色号拆分商品
        	Map<String, List<SkuList>> skuColors = new HashMap<>();
			for(StoreProductAttrValue value : values) {
			    String[] suks = value.getSuk().split(",");
			    String color = suks.length > 1 ? suks[1].split(";")[0] : "";

			    SkuList sku = new SkuList();
			    sku.setRetailPrice(value.getOtPrice().multiply(new BigDecimal("8")));
			    sku.setSize(suks.length > 1 ? suks[1] : suks[0]);
			    sku.setStock(value.getStock());
			    sku.setBarcode(value.getSourceSkuId());
			    sku.setCostPrice(value.getCost());
			    sku.setSupplyPrice(value.getPrice());
			    
			    List<SkuList> skuList = skuColors.get(color);
			    if(null == skuList) {
			    	skuList = new ArrayList<>();
			    	skuList.add(sku);
			    	skuColors.put(color, skuList);
			    } else {
			    	skuList.add(sku);
			    }
			}

			List<ImProductStockDTO> imProductStocks = new ArrayList<>();
			for(Map.Entry<String, List<SkuList>> m : skuColors.entrySet()) {
				String color = m.getKey();
			    List<SkuList> skuList = m.getValue();
				
			    for(SkuList sku : skuList) {
			    	ImProductStockDTO imProductStockDTO = new ImProductStockDTO();
			    	imProductStockDTO.setBoutiqueId(product.getBarCode() + "-" + color);
			    	imProductStockDTO.setSize(sku.getSize());
			    	imProductStockDTO.setStock(sku.getStock());
			    	imProductStocks.add(imProductStockDTO);
			    }
			}
		    
			// 库存更新
		    RestTemplate restTemplate = restTemplateConfig.restTemplate();
		    HttpHeaders headers = new HttpHeaders();
		    headers.setContentType(MediaType.APPLICATION_JSON);
		    headers.add("Auth-Token", imPushToken);
		    JSONArray jsonArr = JSONArray.parseArray(JSONArray.toJSONString(imProductStocks));
		    HttpEntity<JSONArray> formEntity = new HttpEntity<>(jsonArr, headers);
		    ResponseEntity<String> response = restTemplate.postForEntity(imPushDomain + imPushUpdateStock, formEntity, String.class);
		    
		    if (HttpStatus.OK != response.getStatusCode()) {
		    	JSONObject message = JSONObject.parseObject(response.getBody());
		    	String errorMessage = message.getString("error");
		    	
		    	log.info("--------------- IM商品反向库存更新: {} 推送异常: {} ---------------", jsonArr, errorMessage);
		    }
		    Boolean b = JSONObject.parseObject(response.getBody()).getBoolean("success");
		    if(!b) {
		    	log.info("--------------- IM商品反向库存更新推送失败---------------", jsonArr);
		    }
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    /**
     * 获取批次
     * @author daigb
     * @date:  2022-03-31 16:21
     */
    public String getImPushProductBatch() {
    	String batchId = null;
    	try {
    		RestTemplate restTemplate = new RestTemplateConfig().restTemplate();
    		HttpHeaders headers = new HttpHeaders();
    		headers.setContentType(MediaType.APPLICATION_JSON);
    		headers.add("Auth-Token", imPushToken);
    		HttpEntity<String> formEntity = new HttpEntity<>(null, headers);
    		ResponseEntity<String> response = restTemplate.exchange(imPushDomain + imPushProductBatch, HttpMethod.GET, formEntity, String.class);
    		
    		System.out.println(response);
			if (HttpStatus.OK != response.getStatusCode()) {
				JSONObject message = JSONObject.parseObject(response.getBody());
				String errorMessage = message.getString("error");
				
				log.info("--------------- IM商品反向批次获取异常: {} ---------------", errorMessage);
			}
			Boolean b = JSONObject.parseObject(response.getBody()).getBoolean("success");
			if(!b) {
				log.info("--------------- IM商品反向批次获取失败---------------");
			} else {
				batchId = JSONObject.parseObject(response.getBody()).getJSONObject("data").getString("batchId");
			}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	
    	return batchId;
    }
    
    /**
     * 结束批次
     * @author daigb
     * @date:  2022-03-31 16:21
     */
    public void endImPushProductBatch(String batchId, Integer total) {
        try {
			// 批次结束
		    RestTemplate restTemplate = restTemplateConfig.restTemplate();
		    HttpHeaders headers = new HttpHeaders();
		    headers.setContentType(MediaType.APPLICATION_JSON);
		    headers.add("Auth-Token", imPushToken);
		    // 参数
		    StringBuilder sb = new StringBuilder();
		    sb.append("?batchId=");
		    sb.append(batchId);
		    sb.append("&total=");
		    sb.append(total);
		    
		    HttpEntity<JSONArray> formEntity = new HttpEntity<>(null, headers);
		    ResponseEntity<String> response = restTemplate.postForEntity(imPushDomain + imPushProductEndBatch + sb, formEntity, String.class);
		    
		    if (HttpStatus.OK != response.getStatusCode()) {
		    	JSONObject message = JSONObject.parseObject(response.getBody());
		    	String errorMessage = message.getString("error");
		    	
		    	log.info("--------------- IM商品反向结束批次异常: {} ---------------", errorMessage);
		    }
		    Boolean b = JSONObject.parseObject(response.getBody()).getBoolean("success");
		    if(!b) {
		    	log.info("--------------- IM商品反向结束批次推送失败---------------");
		    } else {
		    	log.info("--------------- IM商品反向结束批次成功---------------");
		    }
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

    /******************* end ********************/

    /******************* xyy ********************/
    /**
     * 查询分页商品数据
     * @Description:  
     * @author daigb 
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public XyyProductResDTO selectXyyPage(Integer pageNow, Integer pageSize, Long time, String token) throws Exception {
        // 组装请求url
        XyyProductResDTO xyyProductResDTO = null;
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(xyyUrl);
			sb.append("/Index/t/");
			sb.append(time);
			sb.append("/r/");
			sb.append(time);
			sb.append("/appkey/");
			sb.append(xyyAppKey);
			sb.append("/secret/");
			sb.append(xyyAppSecret);
			sb.append("/s/");
			sb.append(token);
			sb.append("/p/");
			sb.append(pageNow);
			sb.append("/n/");
			sb.append(pageSize);
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);

			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- xyy查询分页商品数据异常{} ---------------", errorMessage);
			}

			ObjectMapper mapper = new ObjectMapper();
			xyyProductResDTO = mapper.readValue(response.getBody(), XyyProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return xyyProductResDTO;
    }

    /**
     * 获取商品sku
     * @Description:  
     * @author daigb 
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public List<XyyProductSkuResDTO> getXyySkus(Integer goodsId, Long time, String token) throws Exception {
        // 组装请求url
        List<XyyProductSkuResDTO> xyyProductSkuResDTOs = null;
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(xyyUrl);
			sb.append("/getGoodsStock/t/");
			sb.append(time);
			sb.append("/r/");
			sb.append(time);
			sb.append("/appkey/");
			sb.append(xyyAppKey);
			sb.append("/secret/");
			sb.append(xyyAppSecret);
			sb.append("/s/");
			sb.append(token);
			sb.append("/gid/");
			sb.append(goodsId);
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- xyy获取商品sku异常{} ---------------", errorMessage);
			}

			ObjectMapper mapper = new ObjectMapper();
			JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, XyyProductSkuResDTO.class);
			xyyProductSkuResDTOs = mapper.readValue(response.getBody(), javaType);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return xyyProductSkuResDTOs;
    }

    public String getXyyToken(long time) {
        // 生成秘钥
        String sign = null;
		try {
			sign = DigestUtils.sha1Hex(time + "" + time + xyyAppKey + xyyAppSecret);
//        String sign = DigestUtils.sha1Hex(time + "" + time + "xunwu" + "xunwucec51ef9aa7663d9675b0104749495skocFg");
			sign = DigestUtils.md5Hex(sign);
			sign = DigestUtils.md5Hex(sign);
			sign = sign.toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
        return sign;
    }

    /******************* end ********************/

    /******************* leam ********************/

    /**
     * 获取图片前缀url
     */
    public String selectImageUrl() {
        //组装请求url
        JSONObject message = null;
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(leamUrl)
			        .append("/ApiV3/token/")
			        .append(leamToken);
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- leam获取图片前缀url异常{} ---------------", errorMessage);
			}
			message = JSONObject.parseObject(response.getBody());
		} catch (Exception e) {
			e.printStackTrace();
		}
        return message.getString("image_url");
    }

    /**
     * 获取产品列表
     * @return
     */
    public LeamProductResDTO selectLeam() throws Exception {
        //组装请求url
        LeamProductResDTO leamProductResDTO = null;
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(leamUrl)
			        .append("/ApiV3/token/")
			        .append(leamToken)
			        .append("/callType/allStockGroup");
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- leam获取产品列表异常{} ---------------", errorMessage);
			}
			ObjectMapper mapper = new ObjectMapper();
			leamProductResDTO = mapper.readValue(response.getBody(), LeamProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return leamProductResDTO;
    }


    /******************* end ********************/
    
    /******************* jky ********************/
    /**
     * 查询分页商品数据
     * @Description:  
     * @author daigb 
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public static JkyProductResDTO selectJkyPage(Integer pageNow, Integer pageSize, String goodsNo) throws Exception {
        JkyProductResDTO jkyProductResDTO = null;
		try {
			JackyunGoodsRequest jackyunGoodsRequest = new JackyunGoodsRequest();
			jackyunGoodsRequest.setPageIndex(pageNow);
			jackyunGoodsRequest.setPageSize(pageSize);
			if(StringUtil.isNotEmpty(goodsNo)) {
				jackyunGoodsRequest.setGoodsNo(goodsNo);
			}
			String result = JackyunOpenHttpUtils.post("erp.storage.goodslist", "v1.0", jackyunGoodsRequest);

			ObjectMapper mapper = new ObjectMapper();
			jkyProductResDTO = mapper.readValue(result, JkyProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        return jkyProductResDTO;
    }
    
    /**
     * 分页获取批次仓库sku信息
     * @Description:  
     * @author daigb 
     * @param @param goodsNo
     * @param @return
     * @param @throws Exception
     * @return JkyProductSkuResDTO
     * @throws
     */
    public JkyProductSkuResDTO pageJkyBatchSkus(Integer pageNow, Integer pageSize, String warehouseCode) throws Exception {
        JkyProductSkuResDTO jkyProductSkuResDTO = null;
		try {
			JackyunGoodsRequest jackyunGoodsRequest = new JackyunGoodsRequest();
			jackyunGoodsRequest.setPageIndex(pageNow);
			jackyunGoodsRequest.setPageSize(pageSize);
			jackyunGoodsRequest.setWarehouseCode(warehouseCode);
			String result = JackyunOpenHttpUtils.post("erp.batchstockquantity.get", "v1.0", jackyunGoodsRequest);
			ObjectMapper mapper = new ObjectMapper();
			jkyProductSkuResDTO = mapper.readValue(result, JkyProductSkuResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return jkyProductSkuResDTO;
    }
    
    /**
     * @throws Exception 
     * 分页获取仓库sku信息
     * @Description:  
     * @author daigb 
     * @param @param goodsNo
     * @param @return
     * @param @throws Exception
     * @return List<GoodsStockQuantity>
     * @throws
     */
    public JkyProductSkuResDTO pageJkySkus(Integer pageNow, Integer pageSize, String warehouseCode) throws Exception {
        JkyProductSkuResDTO jkyProductSkuResDTO = null;
		try {
			JackyunGoodsRequest jackyunGoodsRequest = new JackyunGoodsRequest();
			jackyunGoodsRequest.setPageIndex(pageNow);
			jackyunGoodsRequest.setPageSize(pageSize);
			jackyunGoodsRequest.setWarehouseCode(warehouseCode);
			String result = JackyunOpenHttpUtils.post("erp.stockquantity.get", "v1.0", jackyunGoodsRequest);
			ObjectMapper mapper = new ObjectMapper();
			jkyProductSkuResDTO = mapper.readValue(result, JkyProductSkuResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        return jkyProductSkuResDTO;
    }
    
    /**
     * 获取商品sku价格
     * @Description:  
     * @author daigb 
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public JkyProductSkuPriceResDTO getJkySkuPrice(String skuBarcode, String goodsNo) throws Exception {
        JkyProductSkuPriceResDTO jkyProductSkuPriceResDTO = null;
		try {
			JackyunGoodsRequest jackyunGoodsRequest = new JackyunGoodsRequest();
			if(StringUtil.isNotEmpty(skuBarcode)) {
				jackyunGoodsRequest.setSkuBarcode(skuBarcode);
			}
			if(StringUtil.isNotEmpty(goodsNo)) {
				jackyunGoodsRequest.setGoodsNo(goodsNo);
			}
			String result = JackyunOpenHttpUtils.post("erp.pricelist.get", "v1.0", jackyunGoodsRequest);
			ObjectMapper mapper = new ObjectMapper();
			jkyProductSkuPriceResDTO = mapper.readValue(result, JkyProductSkuPriceResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        return jkyProductSkuPriceResDTO;
    }
    
    /**
     * @return 
     * 查询待出库商品
     * @Description:  
     * @author daigb 
     * @param @param product
     * @param @param values
     * @param @param category
     * @param @param markupRate
     * @param @throws Exception
     * @return void
     * @throws
     */
    public static List<StockOutDetailView> selectOutJkyGoods(String id) throws Exception {
        // 先查询商品sku信息, 将库存出库
        List<StockOutDetailView> stockOutDetailViews = null;
		try {
			stockOutDetailViews = new ArrayList<>();
			List<GoodsStockQuantity> goodsStockQuantitys = getJkySkus(id);
			for(GoodsStockQuantity stockQuantity : goodsStockQuantitys) {
			    if(Integer.parseInt(stockQuantity.getCurrentQuantity()) > 0) {
			        StockOutDetailView stockOutDetailView = new StockOutDetailView();
			        stockOutDetailView.setSkuBarcode(stockQuantity.getSkuBarcode());
			        stockOutDetailView.setRelDetailId(0);
			        stockOutDetailView.setSkuCount(new BigDecimal(stockQuantity.getCurrentQuantity()));
			        stockOutDetailView.setIsCertified("1");
			        stockOutDetailViews.add(stockOutDetailView);
			    }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        return stockOutDetailViews;
    }
    
    /**
     * @return 
     * 组装待创建商品
     * @Description:  
     * @author daigb 
     * @param @param product
     * @param @param values
     * @param @param category
     * @param @param markupRate
     * @param @throws Exception
     * @return void
     * @throws
     */
    public Map<String, Object> createJkySkus(StoreProduct product, List<StoreProductAttrValue> values, Category category, BigDecimal markupRate) throws Exception {
        Map<String, Object> map = null;
		try {
			map = new HashMap<>();
			List<BaseRequestBizData> goodsList = new ArrayList<>();
			List<BaseRequestBizData> jsonStrs = new ArrayList<BaseRequestBizData>();
			List<StockInDetailView> stockInDetailViews = new ArrayList<>();
			JSONArray sliderImage = JSONArray.parseArray(product.getSliderImage());
			// 查询货品skuid
			JkyProductResDTO jkyProductResDTO = selectJkyPage(0, 200, product.getId().toString());
			
			// 组装吉客云商品信息
			for(StoreProductAttrValue value : values) {
				// 查询商品是否有匹配到
            	JkyContrast jkyContrast = compJkyNo(product, value);
            	if(null == jkyContrast) {
            		continue;
            	}
			    // 商品和sku信息
			    JackyunGoodsAddRequest goods = new JackyunGoodsAddRequest();
			    goods.setGoodsName(product.getStoreName());
			    goods.setGoodsNo(jkyContrast.getGoodsNo());
			    goods.setGoodsAlias(product.getKeyword());
			    goods.setCateCode(product.getCateId()+"");
			    goods.setCateName(category.getName());
			    goods.setBrandName(product.getBrandName());
			    goods.setUnitName(product.getUnitName());
			    if(!value.getSuk().contains(";") && !StringUtil.isEmpty(product.getColorCode())) {
			    	goods.setSkuName(product.getColorCode() + "," + value.getSuk());
			    } else {
			    	goods.setSkuName(value.getSuk().replace(";", ","));
			    }
			    goods.setOutSkuCode(value.getSourceSkuId());
			    goods.setSkuBarcode(jkyContrast.getSkuNo());
			    goods.setSkuNo(jkyContrast.getSkuNo());
			    goods.setMainBarcode(product.getKeyword()); // 公码
			    goods.setMainGoodsUrl(product.getImage());
			    goods.setSkuImageUrl(value.getImage());
			    if(null != sliderImage) {
			    	if(4 < sliderImage.size()) {
			    		goods.setTopGoodsUrl(sliderImage.getString(1));
			    		goods.setBelowGoodsUrl(sliderImage.getString(2));
			    		goods.setLeftGoodsUrl(sliderImage.getString(3));
			    		goods.setRightGoodsUrl(sliderImage.getString(4));
			    	} else {
			    		for(int i=0; i<sliderImage.size(); i++) {
			    			if(i == 0) {
			    				goods.setTopGoodsUrl(sliderImage.getString(i));
			    			} else if(i == 1) {
			    				goods.setBelowGoodsUrl(sliderImage.getString(i));
			    			} else if(i == 2) {
			    				goods.setLeftGoodsUrl(sliderImage.getString(i));
			    			} else if(i == 3) {
			    				goods.setRightGoodsUrl(sliderImage.getString(i));
			    			}
			    		}
			    	}
			    }
			    
			    goods.setDescript("");
			    goodsList.add(goods);

			    // 价格
			    BigDecimal price = value.getPrice().add(value.getPrice().multiply(markupRate.multiply(new BigDecimal("0.01"))).setScale(2, RoundingMode.HALF_UP));
			    JackyunGoodsSkuAddRequest skuPrice = new JackyunGoodsSkuAddRequest();
			    skuPrice.setSkuName(goods.getSkuName());
			    skuPrice.setRetailPrice(price);
			    skuPrice.setSkuWeight(value.getOtPrice()); // 原价往重量上赋值
			    skuPrice.setSkuBarcode(jkyContrast.getSkuNo());
			    // 匹配吉客云skuId
                List<Goods> jkyGoodsList = jkyProductResDTO.getResult().getDataResult().getGoods();
                for(Goods g : jkyGoodsList) {
                	if(null == g.getSkuCode()) {
                		continue;
                	}
                	if(g.getSkuCode().equals(goods.getSkuNo())) {
                		skuPrice.setSkuId(g.getSkuId());
                		break;
                	}
                }
                if(StringUtil.isEmpty(skuPrice.getSkuId())) {
                	// 占位
            		skuPrice.setSkuId(jkyContrast.getSkuNo());
                }
			    jsonStrs.add(skuPrice);

			    // 库存
			    StockInDetailView stockInDetailView = new StockInDetailView();
			    stockInDetailView.setSkuBarcode(jkyContrast.getSkuNo());
			    stockInDetailView.setRelDetailId(0);
			    stockInDetailView.setSkuCount(new BigDecimal(value.getStock()));
			    stockInDetailView.setIsCertified("1");
			    stockInDetailViews.add(stockInDetailView);
			}

			map.put("goodsList", goodsList);
			map.put("jsonStrs", jsonStrs);
			map.put("stockInDetailViews", stockInDetailViews);
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        return map;
    }
    
    // 匹配吉客云货品编号
    private JkyContrast compJkyNo(StoreProduct product, StoreProductAttrValue value) {
    	String keyword = product.getKeyword();
    	String color = product.getColorCode();
    	String season = product.getSeasonCode();
    	String[] suk = value.getSuk().split(",");
    	String size = suk.length > 1 ? suk[1] : suk[0];
    	List<JkyContrast> jkyContrasts;
    	
    	// IM匹配规则, 暂时弃用
//    	if(StringUtil.isEmpty(keyCode)) {
//    		return null;
//    	}
//    	keyCode = keyCode.substring(0, 8);
//    	
//		List<JkyContrast> jkyContrasts = jkyContrastService.list(Wrappers.<JkyContrast>lambdaQuery()
//            		.likeRight(JkyContrast :: getGoodsNo, keyCode)
//            		.eq(StringUtil.isNotEmpty(season), JkyContrast :: getSeasonCode, season)
//            		);
//		for(JkyContrast jkyContrast : jkyContrasts) {
//			String jkySku = jkyContrast.getSuk();
//			String[] jkySkus = jkySku.split(";");
//			String colorCode = jkySkus[0].split(" ")[0].replaceAll("[^\\d]+", "");
//			// 有色号
//			if(jkySkus.length > 1 && StringUtil.isNotEmpty(color)) {
//				if(!colorCode.equals(color)) {
//					continue;
//				}
//			}
//			// 匹配尺码
//			String[] sizes = jkySkus.length > 1 ? jkySkus[1].split("=") : jkySkus[0].split("=");
//			if(size.equals(sizes[0]) || size.equals(sizes[1])) {
//				// 新增库存
//				jkyContrastService.update(Wrappers.<JkyContrast>lambdaUpdate()
//						.eq(JkyContrast :: getId, jkyContrast.getId())
//						.set(JkyContrast :: getStock, jkyContrast.getStock() + value.getStock())
//						);
//				return jkyContrast;
//			}
//		}
    	
		// 01-BELLETTINI店铺规则
		if(product.getIsEurope() == ProductTypeEnum.BELLETTINI.getCode()) {
			// 拆分本地编码与色号
			StoreProductDescription description = storeProductDescriptionService.getOne(Wrappers.<StoreProductDescription>lambdaQuery().eq(StoreProductDescription :: getProductId, product.getId()));
			String key = "DESIGNER ID: ";
			String descriptionName = description.getDescription();
			if(!descriptionName.contains(key) || !keyword.contains(" ")) {
				return null;
			}
			String[] keyCodes = descriptionName.substring(descriptionName.indexOf(key), descriptionName.length()).replace(key, "").split(" ");
			String keyCode = keyCodes[0].substring(0, 8);
			if(keyCodes.length < 2) {
				return null;
			}
			String colorCode = keyCodes[1];
			
			jkyContrasts = jkyContrastService.list(Wrappers.<JkyContrast>lambdaQuery()
	            		.likeRight(JkyContrast :: getGoodsNo, keyCode)
	            		);
			
			return matchJkyColor(jkyContrasts, size, colorCode, value.getStock());
		} else if(product.getIsEurope() == ProductTypeEnum.UNIBUY.getCode() || product.getIsEurope() == ProductTypeEnum.UNIBUY1.getCode()) {
			// 后期注意是否被处理默认规格
			String[] sizeUnibuy = size.split(";");
	    	size = sizeUnibuy.length > 1 ? sizeUnibuy[1] : sizeUnibuy[0];
	    	
			String keyCode = null;
			String colorCode = null;
			String storeName = null;
	        Matcher mZ = Pattern.compile(".*[a-zA-Z]+.*").matcher(keyword);
	        Matcher mSS = Pattern.compile("[0-9]*").matcher(keyword.charAt(0)+"");
	        Matcher mSZ = Pattern.compile("[a-zA-Z]*").matcher(keyword.charAt(0)+"");
			
	        // 规则匹配
			if(keyword.contains("-")) {
				String[] codes = keyword.split("-");
				// 方案1: 以2中划线区分, 1编号, 3色号
				if(codes.length >= 3) {
					keyCode = codes[0].substring(0, 8);
					colorCode = codes[2];
			    // 方案2: 一个中划线前面是品名, 2只取数字为色号
				} else if(codes.length == 2) {
					storeName = codes[0];
					colorCode = codes[1].split("[^\\d]+")[0];
				}
			} else if(keyword.contains("_")) {
				String[] codes = keyword.split("_");
				// 方案6: 有两个下划线, 1是编号, 3是色号
				if(codes.length >= 3) {
					keyCode = codes[0].substring(0, 8);
					colorCode = codes[2];
				// 方案5: 有一个下划线, 前面是编号, 后面三位是色号
				} else if(codes.length == 2 && codes[0].length() > 7 && codes[0].length() > 2) {
					keyCode = codes[0].substring(0, 8);
					colorCode = codes[1].substring(codes[1].length()-3, codes[1].length());
				}
			} else if(keyword.contains(" ")) {
				String[] codes = keyword.split(" ");
				// 方案8: 有空格, 前面编号, 后面色号
				keyCode = codes[0].substring(0, 8);
				colorCode = codes[1];
			} else if(!mZ.matches() && keyword.length() > 10) {
				// 方案4: 全数字类型, 前八位是编号, 后三位是色号
				keyCode = keyword.substring(0, 8);
				colorCode = keyword.substring(keyword.length()-3, keyword.length());
			} else if(mZ.matches()) {
				// 方案3: 没有中划线, 数字打头中间有英文, 英文前面为编号, 后面是色号
				if(mSS.matches()) {
					String[] codes = keyword.split("[^\\d]+");
					keyCode = codes[0].substring(0, 8);
					colorCode = codes[1];
				// 方案7: 英文打头, 英文是品名, 数字是色号
				} else if(mSZ.matches()) {
			    	Pattern p = Pattern.compile("[a-zA-Z]+|\\d+");
			    	Matcher m = p.matcher(keyword);
			    	ArrayList<String> allMatches = new ArrayList<>();
			    	while (m.find()) {
			    		allMatches.add(m.group());
			    	}
			    	if(1 < allMatches.size()) {
			    		storeName = allMatches.get(0);
			    		colorCode = allMatches.get(1);
			    	}
				}
			}

            LambdaQueryWrapper<JkyContrast> lambdaQueryWrapper =  new LambdaQueryWrapper<>();
			if(StringUtil.isNotEmpty(keyCode)) {
				lambdaQueryWrapper.likeRight(JkyContrast :: getGoodsNo, keyCode);
			} else if(StringUtil.isNotEmpty(storeName)) {
				lambdaQueryWrapper.like(JkyContrast :: getGoodsName, storeName);
			}
			jkyContrasts = jkyContrastService.list(lambdaQueryWrapper);

			return matchJkyColor(jkyContrasts, size, colorCode, value.getStock());
		} else if(product.getIsEurope() == ProductTypeEnum.CAROTTA.getCode()) {
			// 拆分本地编码与色号
			String[] codes = keyword.split("[^\\d]+");
			if(codes.length < 2) {
				return null;
			}
			String keyCode = codes[0].substring(0, 8);
			String colorCode = codes[1];

			jkyContrasts = jkyContrastService.list(Wrappers.<JkyContrast>lambdaQuery()
	            		.likeRight(JkyContrast :: getGoodsNo, keyCode)
	            		);
			return matchJkyColor(jkyContrasts, size, colorCode, value.getStock());
		}
		
		return null;
    }
    
    private JkyContrast matchJkyColor(List<JkyContrast> jkyContrasts, String size, String colorCode, Integer stock) {
		for(JkyContrast jkyContrast : jkyContrasts) {
			// 拆分吉客云色号与尺码
			String jkySku = jkyContrast.getSuk();
			String[] jkySkus = jkySku.split(";");
			String jkyColorCode = jkySkus[0].split(" ")[0].replaceAll("[^\\d]+", "");
			// 匹配尺码
			String[] sizes = jkySkus.length > 1 ? jkySkus[1].split("=") : jkySkus[0].split("=");
			boolean sizeType = false;
			if(sizes.length < 2) {
				sizeType = size.equals(sizes[0]);
			} else {
				sizeType = size.equals(sizes[0]) || size.equals(sizes[1]);
			}
			
			if(jkyColorCode.equals(colorCode) && sizeType) {
				// 新增库存
				jkyContrastService.update(Wrappers.<JkyContrast>lambdaUpdate()
						.eq(JkyContrast :: getId, jkyContrast.getId())
						.set(JkyContrast :: getStock, jkyContrast.getStock() + stock)
						);
				
				return jkyContrast;
			}
		}
		
    	return null;
    }
    
    /**
     * 批量创建商品价格
     * @Description:  
     * @author daigb 
     * @param @param goodsNo
     * @param @param skuBarcode
     * @param @throws Exception
     * @return void
     * @throws
     */
    public static void createJkyGoodsSku(List<BaseRequestBizData> jsonStrs) throws Exception {
    	String result = JackyunOpenHttpUtils.post("erp.goodsku.updatebyskubarcode", "v1.0", jsonStrs);
        if(500 == JSONObject.parseObject(result).getInteger("code")) {
        	log.info("--------------- 吉客云创建sku价格: {}", result);
        }
    }
    
    /**
     * 生成入库单
     * @Description:  
     * @author daigb 
     * @param @throws Exception
     * @return void
     * @throws
     */
    public static void createJkyGoodsStockIn(List<StockInDetailView> stockInDetailViews) throws Exception {
        JackyunGoodsStockInRequest stock = new JackyunGoodsStockInRequest();
        stock.setApplyDepartCode("CP003");
        stock.setApplyCompanyCode("0001");
        stock.setInWarehouseCode("019");
        stock.setInType(104);
        stock.setRelDataId(System.currentTimeMillis() + "");
        stock.setApplyUserName("daigb");
        stock.setApplyDate(new Date());
        stock.setOperator("daigb");
        stock.setSource("OPEN");
        stock.setLogisticNo("SF888888888888");
        stock.setStockInDetailViews(stockInDetailViews);
        
        String result = JackyunOpenHttpUtils.post("erp.stock.createandstockin", "v1.0", stock);
        if(500 == JSONObject.parseObject(result).getInteger("code")) {
        	log.info("--------------- 吉客云入库: {}", result);
        }
    }
    
    /**
     * 生成出库单
     * @Description:  
     * @author daigb 
     * @param @throws Exception
     * @return void
     * @throws
     */
    public static void createJkyGoodsStockOut(List<StockOutDetailView> stockOutDetailViews) throws Exception {
        JackyunGoodsStockOutRequest stock = new JackyunGoodsStockOutRequest();
        stock.setOutWarehouseCode("019");
        stock.setOutType(204);
        Long l = System.currentTimeMillis();
        stock.setRelDataId(l + "");
        stock.setApplyDepartName("daigb");
        stock.setApplyDate(new Date());
        stock.setOperator("daigb");
        stock.setSource("OPEN");
        
        stock.setStockOutDetailViews(stockOutDetailViews);
        
        String result = JackyunOpenHttpUtils.post("erp.stock.createandstockout", "v1.0", stock);
        if(500 == JSONObject.parseObject(result).getInteger("code")) {
        	log.info("--------------- 吉客云出库: {}", result);
        }
    }
    
    /**
     * @throws Exception 
     * 单商品库存查询
     * @Description:  
     * @author daigb 
     * @param @param goodsNo
     * @param @return
     * @param @throws Exception
     * @return JkyProductSkuResDTO
     * @throws
     */
    public static List<GoodsStockQuantity> getJkySkus(String goodsNo) throws Exception {
        List<GoodsStockQuantity> goodsStockQuantitys = null;
		try {
			JackyunGoodsRequest jackyunGoodsRequest = new JackyunGoodsRequest();
			jackyunGoodsRequest.setPageIndex(0);
			jackyunGoodsRequest.setPageSize(200);
			jackyunGoodsRequest.setWarehouseCode("019");
			jackyunGoodsRequest.setGoodsNo(goodsNo);
			String result = JackyunOpenHttpUtils.post("erp.stockquantity.get", "v1.0", jackyunGoodsRequest);
			ObjectMapper mapper = new ObjectMapper();
			JkyProductSkuResDTO jkyProductSkuResDTO = mapper.readValue(result, JkyProductSkuResDTO.class);
			goodsStockQuantitys = jkyProductSkuResDTO.getResult().getDataResult().getGoodsStockQuantity();
		} catch (Exception e) {
			e.printStackTrace();
		}
        return goodsStockQuantitys;
    }
    
    /******************* end ********************/
    
    /******************* vietti ********************/
    /**
     * 查询分页商品数据
     * @Description:  
     * @author daigb 
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public ViettiProductResDTO selectViettiPage() throws Exception {
        ViettiProductResDTO viettiProductResDTO = null;
		try {
			// 组装请求url
			StringBuilder sb = new StringBuilder();
			sb.append(viettiDomian);
			sb.append("/");
			sb.append(viettiClient);
			sb.append(viettiProducts);
			sb.append("?channelKey=");
			sb.append(viettiAppSecret);
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
			headers.add("Ocp-Apim-Subscription-Key", viettiAppKey);
			HttpEntity<String> entity = new HttpEntity<String>(headers);
			ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, entity, String.class);

			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- vietti查询分页商品数据异常{} ---------------", errorMessage);
			}

			ObjectMapper mapper = new ObjectMapper();
			viettiProductResDTO = mapper.readValue(response.getBody(), ViettiProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return viettiProductResDTO;
    }

    /**
     * 获取单个商品sku
     * @param productId
     * @return
     */
    public ViettiProductSkuRes getViettiSku(String productId) {
        ViettiProductSkuRes viettiProductSkuRes = null;
    	try {
	        // 组装请求url
	        StringBuilder sb = new StringBuilder();
	        sb.append(viettiDomian);
	        sb.append("/");
	        sb.append(viettiClient);
	        sb.append(viettiProducts)
	                .append("/").append(productId);
	        sb.append("?channelKey=");
	        sb.append(viettiAppSecret);
	        // 发送请求
	        RestTemplate restTemplate = restTemplateConfig.restTemplate();
	        HttpHeaders headers = new HttpHeaders();
	        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
	        headers.add("Ocp-Apim-Subscription-Key", viettiAppKey);
	        HttpEntity<String> entity = new HttpEntity<String>(headers);
	        ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, entity, String.class);
	        if (HttpStatus.OK != response.getStatusCode()) {
	            JSONObject message = JSONObject.parseObject(response.getBody());
	            String errorMessage = message.getString("error");

	            log.info("--------------- Vietti获取单个商品sku异常{} ---------------", errorMessage);
	        }
	        ObjectMapper mapper = new ObjectMapper();
            viettiProductSkuRes = mapper.readValue(response.getBody(), ViettiProductSkuRes.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return viettiProductSkuRes;
    }
    
    /**
     * 获取商品sku
     * @Description:  
     * @author daigb 
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public ViettiProductSkuResDTO getViettiSkus() throws Exception {
        // 组装请求url
        ViettiProductSkuResDTO viettiProductSkuResDTO = null;
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(viettiDomian);
			sb.append("/");
			sb.append(viettiClient);
			sb.append(viettiStocks);
			sb.append("?channelKey=");
			sb.append(viettiAppSecret);
			// 发送请求
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
			headers.add("Ocp-Apim-Subscription-Key", viettiAppKey);
			HttpEntity<String> entity = new HttpEntity<String>(headers);
			ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, entity, String.class);

			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- Vietti获取商品sku异常{} ---------------", errorMessage);
			}

			ObjectMapper mapper = new ObjectMapper();
			viettiProductSkuResDTO = mapper.readValue(response.getBody(), ViettiProductSkuResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

        return viettiProductSkuResDTO;
    }
    
    /******************* end ********************/


    /******************* lavita ********************/
    /**
     * 查询分页商品数据
     * @Description:
     * @author songjc
     * @param @param pageNow
     * @param @param pageSize
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public LavitaProductResDTO selectLavitaPage(int pageNum,int pageSize) {
        // 组装请求url
        LavitaProductResDTO lavitaProductResDTO=null;
        try {
            StringBuilder url = new StringBuilder();
            url.append(lavitaDomian);
            url.append(lavitaProducts);
            url.append("?appid=");
            url.append(lavitaAppid);
            // 发送请求
            RestTemplate restTemplate = restTemplateConfig.restTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

            JSONObject jsonObject = new JSONObject();
            //设置参数
            //生成令牌
            String lavitaToken = DigestUtil.md5Hex("appid="+lavitaAppid+"&appsecret="+lavitaAppsecret+"&times="+DateUtil.format(new Date(),"yyyy-MM-dd"));
            jsonObject.put("token", lavitaToken);
            jsonObject.put( "limit", pageSize);
            jsonObject.put( "offset",pageNum);

            HttpEntity<String> request = new HttpEntity(jsonObject, headers);
            ResponseEntity<String> response = restTemplate.exchange(url.toString(), HttpMethod.POST, request, String.class);

            if (HttpStatus.OK != response.getStatusCode()) {
                JSONObject message = JSONObject.parseObject(response.getBody());
                String errorMessage = message.getString("error");

                log.info("--------------- lavita查询分页商品数据异常{} ---------------", errorMessage);
            }

            ObjectMapper mapper = new ObjectMapper();
            lavitaProductResDTO = mapper.readValue(response.getBody(), LavitaProductResDTO.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lavitaProductResDTO;
    }

    /**
     * 获取单个商品sku
     * @param kuanId
     * @return
     */
    public LavitaProductSkuRes getLavitaSku(String kuanId) {
        // 组装请求url
        LavitaProductSkuRes lavitaProductSkuRes = null;
        try {
            StringBuilder url = new StringBuilder();
            url.append(lavitaDomian);
            url.append(productInfo);
            url.append("?appid=");
            url.append(lavitaAppid);
            // 发送请求
            RestTemplate restTemplate = restTemplateConfig.restTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

            JSONObject jsonObject = new JSONObject();
            //设置参数
            //生成令牌
            String lavitaToken = DigestUtil.md5Hex("appid="+lavitaAppid+"&appsecret="+lavitaAppsecret+"&times="+DateUtil.format(new Date(),"yyyy-MM-dd"));
            jsonObject.put("token", lavitaToken);
            jsonObject.put( "kuanId",kuanId);
            jsonObject.put( "SearchEqual", 0);

            HttpEntity<String> request = new HttpEntity(jsonObject, headers);
            ResponseEntity<String> response = restTemplate.exchange(url.toString(), HttpMethod.POST, request, String.class);


            if (HttpStatus.OK != response.getStatusCode()) {
                JSONObject message = JSONObject.parseObject(response.getBody());
                String errorMessage = message.getString("error");

                log.info("--------------- Lavita获取单个商品sku异常{} ---------------", errorMessage);
            }
            ObjectMapper mapper = new ObjectMapper();

            lavitaProductSkuRes = mapper.readValue(response.getBody(), LavitaProductSkuRes.class);
            lavitaProductSkuRes.getDataDetail().setKuanId(kuanId);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return lavitaProductSkuRes;
    }

    /**
     * 获取单个商品sku
     * @param value
     * @return
     */
    public LavitaProductStockRes getLavitaDetail(String value) {
        // 组装请求url
        StringBuilder url = new StringBuilder();
        url.append(lavitaDomian);
        url.append(lavitaStocks);
        url.append("?appid=");
        url.append(lavitaAppid);
        // 发送请求
        RestTemplate restTemplate = restTemplateConfig.restTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

        JSONObject jsonObject = new JSONObject();
        //设置参数
        //生成令牌
        String lavitaToken = DigestUtil.md5Hex("appid="+lavitaAppid+"&appsecret="+lavitaAppsecret+"&times="+DateUtil.format(new Date(),"yyyy-MM-dd"));
        jsonObject.put("token", lavitaToken);
        jsonObject.put( "likeEqualValue",value);
        jsonObject.put( "limit","1000");
        jsonObject.put( "offset", "0");
        jsonObject.put( "likeEqual", "4");
        jsonObject.put( "orderType", "0");

        HttpEntity<String> request = new HttpEntity(jsonObject, headers);
        ResponseEntity<String> response = restTemplate.exchange(url.toString(), HttpMethod.POST, request, String.class);


        if (HttpStatus.OK != response.getStatusCode()) {
            JSONObject message = JSONObject.parseObject(response.getBody());
            String errorMessage = message.getString("error");

            log.info("--------------- Lavita获取单个商品库存异常{} ---------------", errorMessage);
        }
        ObjectMapper mapper = new ObjectMapper();
        LavitaProductStockRes lavitaProductStockRes = null;
        try {
            lavitaProductStockRes = mapper.readValue(response.getBody(), LavitaProductStockRes.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return lavitaProductStockRes;
    }

    /**
     * 获取商品sku
     * @Description:
     * @author songjc
     * @param @param ids
     * @param @return
     * @param @throws Exception
     * @return InProductResDTO
     * @throws
     */
    public LavitaProductSkuResDTO getLavitaSkus() throws Exception {
        // 组装请求url
        StringBuilder sb = new StringBuilder();
        sb.append(lavitaDomian);
        sb.append("/");
        sb.append(lavitaStocks);
        sb.append("?appid=");
        sb.append(lavitaAppid);
        // 发送请求
        RestTemplate restTemplate = restTemplateConfig.restTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("Ocp-Apim-Subscription-Key", lavitaAppid);
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, entity, String.class);

        if (HttpStatus.OK != response.getStatusCode()) {
            JSONObject message = JSONObject.parseObject(response.getBody());
            String errorMessage = message.getString("error");

            log.info("--------------- Lavita获取商品sku异常{} ---------------", errorMessage);
        }

        ObjectMapper mapper = new ObjectMapper();
        LavitaProductSkuResDTO lavitaProductSkuResDTO = mapper.readValue(response.getBody(), LavitaProductSkuResDTO.class);

        return lavitaProductSkuResDTO;
    }

    /******************* end ********************/

    /******************* coltorti ********************/
    public List<ColtortiProductResDTO> selectColtortiPage() throws Exception {
        // 遍历数据
		List<ColtortiProductResDTO> coltortiProductResDTOs = null;
		try {
			String BASIC = "Basic {}";
			String auth = Base64.encode((coltortiUsername + ":" + coltortiPassword).getBytes());

			RestTemplate restTemplate = new RestTemplateConfig().restTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.TEXT_XML);
			headers.add("Authorization", StrUtil.format(BASIC, auth));
			HttpEntity<String> entity = new HttpEntity<String>(headers);
			ResponseEntity<String> response = restTemplate.exchange(coltortiUrl, HttpMethod.GET, entity, String.class);
			String[] resultArr = response.getBody().split("\\r?\\n");
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");

			    log.info("--------------- coltorti获取商品列表异常{} ---------------", errorMessage);
			}

			coltortiProductResDTOs = new ArrayList<ColtortiProductResDTO>();
			for(int i=1; i<resultArr.length; i++) {
			    // 替换规则
			    char[] resultChar = resultArr[i].toCharArray();
			    boolean isString = false;
			    StringBuilder sb = new StringBuilder();
			    for(int z=0; z<resultChar.length; z++) {
			        if("\"".equals(resultChar[z] + "")) {
			            isString = isString ? false : true;
			        }
			        if(";".equals(resultChar[z] + "") && isString) {
			            resultChar[z] = ",".charAt(0);
			        }
			        sb.append(resultChar[z]);
			    }

			    String[] tableContent = sb.toString().replaceAll("\"", "").split(";");
			    if(43 != tableContent.length) {
			        continue;
			    }

			    ColtortiProductResDTO coltortiProductResDTO = new ColtortiProductResDTO();
			    coltortiProductResDTO.setProductUrl(tableContent[0]);
			    coltortiProductResDTO.setImage(tableContent[1]);
			    coltortiProductResDTO.setImage1(tableContent[2]);
			    coltortiProductResDTO.setImage2(tableContent[3]);
			    coltortiProductResDTO.setImage3(tableContent[4]);
			    coltortiProductResDTO.setBrand(tableContent[5]);
			    coltortiProductResDTO.setSkuStyleisnow(tableContent[6]);
			    coltortiProductResDTO.setSeason(tableContent[7]);
			    coltortiProductResDTO.setYear(tableContent[8]);
			    coltortiProductResDTO.setSkuSupplier(tableContent[9]);
			    coltortiProductResDTO.setVariant(tableContent[10]);
			    coltortiProductResDTO.setColorDetail(tableContent[11]);
			    coltortiProductResDTO.setColorSupplier(tableContent[12]);
			    coltortiProductResDTO.setMadeIn(tableContent[13]);
			    coltortiProductResDTO.setMaterial(tableContent[14]);
			    coltortiProductResDTO.setName(tableContent[15]);
			    coltortiProductResDTO.setDescription(tableContent[16]);
			    coltortiProductResDTO.setCategories(tableContent[17]);
			    coltortiProductResDTO.setQty(Integer.parseInt(tableContent[18]));
			    coltortiProductResDTO.setRetailPrice(tableContent[19]);
			    coltortiProductResDTO.setDiscount(tableContent[20]);
			    coltortiProductResDTO.setSizeInfo(tableContent[21]);
			    coltortiProductResDTO.setSize(tableContent[22]);
			    coltortiProductResDTO.setQtyDetail(tableContent[23]);
			    coltortiProductResDTO.setBagLength(tableContent[24]);
			    coltortiProductResDTO.setBagHeight(tableContent[25]);
			    coltortiProductResDTO.setBagWeight(tableContent[26]);
			    coltortiProductResDTO.setHandleHeight(tableContent[27]);
			    coltortiProductResDTO.setShoulderBagLength(tableContent[28]);
			    coltortiProductResDTO.setBeltLength(tableContent[29]);
			    coltortiProductResDTO.setBeltHeight(tableContent[30]);
			    coltortiProductResDTO.setAccessoryLength(tableContent[31]);
			    coltortiProductResDTO.setAccessoryHeight(tableContent[32]);
			    coltortiProductResDTO.setAccessoryWeight(tableContent[33]);
			    coltortiProductResDTO.setHeelHeight(tableContent[34]);
			    coltortiProductResDTO.setPlateauHeight(tableContent[35]);
			    coltortiProductResDTO.setInsoleLength(tableContent[36]);
			    coltortiProductResDTO.setColorStyleisnowIta(tableContent[37]);
			    coltortiProductResDTO.setFta(tableContent[38]);
			    coltortiProductResDTO.setEan(tableContent[39]);
			    coltortiProductResDTO.setNomeIta(tableContent[40]);
			    coltortiProductResDTO.setDescrizioneIta(tableContent[41]);
			    coltortiProductResDTO.setStar(tableContent[42]);
			    coltortiProductResDTO.setCreateTime(new Date());
			    coltortiProductResDTOs.add(coltortiProductResDTO);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    
        return coltortiProductResDTOs;
    }
    /******************* end ********************/
    
    /******************* bellettini ********************/

    public BellettiniProductResDTO getBellettiniProducts() {
        BellettiniProductResDTO bellettiniProductResDTO = null;
		try {
			//组装请求url
			StringBuilder sb = new StringBuilder();
			sb.append(bellettiniUrl);
			HttpHeaders headers = new HttpHeaders();
			headers.add("x-api-key", bellettiniKey);
			headers.add("Content-Type", bellettiniType);
			HttpEntity<String> requestEntity = new HttpEntity<>(headers);
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.exchange(sb.toString(), HttpMethod.GET, requestEntity, String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");
			    log.info("--------------- bellettini获取商品列表异常{} ---------------", errorMessage);
			}
			ObjectMapper mapper = new ObjectMapper();
			bellettiniProductResDTO = mapper.readValue(response.getBody(), BellettiniProductResDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return bellettiniProductResDTO;
    }

    /******************* end ********************/

    /******************* gb ********************/

    /**
     * 获取GB商品
     *
     * @return
     */
    public Map<String,GbProductResDTO> getGbProducts() {
        //        List<GbProductResDTO> list = new ArrayList<>();
		Map<String,GbProductResDTO> map = null;
		try {
			Date date = new Date();
			String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(date);
			log.info("------------------连接ftp:{}服务器----------------------", gbHostName);
			FTPClient ftpClient = new FTPClient();
			//连接ftp
			try {
			    ftpClient.connect(gbHostName);
			} catch (IOException e) {
			    log.error("----------连接ftp异常:{}---------------", e.getMessage());
			}
			//登陆ftp
			try {
			    ftpClient.login(gbUserName, gbPassword);
			} catch (IOException e) {
			    log.error("----------登陆ftp异常:{}---------------", e.getMessage());
			}
			map = new HashMap<>();
			//是否连接成功,成功true,失败false
			if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
			    log.info("--------------登陆ftp成功-------------------");
			    //4.指定要下载的目录, 转移到FTP服务器目录
			    try {
			        ftpClient.changeWorkingDirectory("/");
			    } catch (IOException e) {
			        log.error("----------转移到FTP服务器目录异常:{}---------------", e.getMessage());
			    }
			    //5.遍历下载的目录
			    ftpClient.enterLocalPassiveMode();
			    FTPFile[] ftpFiles = new FTPFile[0];
			    try {
			        ftpFiles = ftpClient.listFiles();
			    } catch (IOException e) {
			        log.error("----------遍历目录文件列表异常:{}---------------", e.getMessage());
			    }
//            log.info("------------当前文件列表:{}------------------", Arrays.toString(ftpFiles));
			    int m = 1;
			    for (int i = 0; i < ftpFiles.length; i++) {
			        String fn = ftpFiles[i].getName();
//                log.info("---------------遍历第{}个文件,fileName:{}--------------------------------", i + 1, ftpFiles[i].getName());
			        //取当天商品文件
			        if (fn.contains(".csv") && fn.contains(dateStr)) {
			            log.info("----------------解析第{}个文件,fileName:{}----------------------",m, ftpFiles[i].getName());
			            InputStream inputStream = null;
			            try {
			                inputStream = ftpClient.retrieveFileStream(fn);
			            } catch (IOException e) {
			                log.error("----------获取文件{}异常:{}---------------", fn, e.getMessage());
			                e.printStackTrace();
			            }
			            if (inputStream != null) {
			                try {
			                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
//                            File newFile = new File(fn);
//                            //将InputStream转File
//                            FileUtils.copyToFile(inputStream, newFile);
//                            BufferedReader br = new BufferedReader(new FileReader(newFile));
			                    String line;
			                    String everyLine;
			                    br.readLine();
			                    // 读取到的内容给line变量
			                    while ((line = br.readLine()) != null) {
			                        everyLine = line;
			                        String[] split = everyLine.split("\",\"");
//                                list.add(setParam(GbProductResDTO.class, split));
			                        GbProductResDTO productResDTO = setParam(GbProductResDTO.class, split);
			                        map.put(productResDTO.getCodArticolo(),productResDTO);
			                    }
			                    inputStream.close();
			                    ftpClient.completePendingCommand();
			                } catch (IOException e) {
			                    log.error("----------转换文件{}异常:{}---------------", fn, e.getMessage());
			                } catch (IllegalAccessException e) {
			                    log.error("----------对象字段大于数据长度:{}---------------", e.getMessage());
			                } catch (InstantiationException e) {
			                    log.error("----------对象实例化异常:{}---------------", e.getMessage());
			                }
			            }
			            m++;

			        }
			    }
			} else {
			    log.info("--------------连接失败-------------------");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
        return map;
    }

    public <T> T setParam(Class<T> clazz, Object[] args) throws IllegalAccessException, InstantiationException {
        T t = null;
		try {
			if (clazz == null || args == null) {
			    throw new IllegalArgumentException();
			}
			t = clazz.newInstance();
			Field[] fields = clazz.getDeclaredFields();
			if (fields.length > args.length) {
			    throw new IndexOutOfBoundsException();
			}
			for (int i = 0; i < fields.length; i++) {
			    fields[i].setAccessible(true);
			    fields[i].set(t, removeQuotation(args[i].toString()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
        return t;
    }

    /**
     * 去字符首尾引号
     *
     * @param str
     * @return
     */
    public String removeQuotation(String str) {
        String result = null;
		try {
			result = "";
			if (StringUtils.isBlank(str)) {
			    return result;
			}
			char[] begins = str.toCharArray();
			int k = 0;
			int m = begins.length;
			char first = begins[0];
			char last = begins[m - 1];
			if (first == '"') {
			    k = 1;
			}
			if (last == '"') {
			    m = m - 1;
			}
			result = str.substring(k, m);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return result;
    }

    /******************* end ********************/


    /******************* carotta ********************/

    /**
     * 获取Carotta产品列表
     * @return
     */
    public CarottaProductResDTO getCarottaProducts(Integer pageSize,String pageInfo) throws JsonProcessingException {
        CarottaProductResDTO carottaProductResDTO = null;
		try {
			StringBuilder sb = new StringBuilder().append("https://")
			        .append(carottaKey)
			        .append(":")
			        .append(carottaPassword)
			        .append("@")
			        .append(carottaUrl)
			        .append("/admin/api/")
			        .append(carottaVersion)
			        .append("/products.json")
			        .append("?limit=")
			        .append(pageSize);
			if(StringUtils.isNotBlank(pageInfo)){
			    sb.append("&page_info=").append(pageInfo);
			}
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");
			    log.info("--------------- 获取Carotta产品列表异常{} ---------------", errorMessage);
			}
			List<String> link = response.getHeaders().get("Link");
			String str = null;
			if(CollectionUtils.isNotEmpty(link)){
			    str = link.stream().map(e -> {
			        if (e.contains("rel=\"next\"")) {
			            String info = StringUtils.substringBetween(e, "page_info=", ">; rel=\"next\"");
			            if(info.contains("page_info=")){
			                info = StringUtils.substringAfter(info, "page_info=");
			            }
			            return info;
			        }
			        return null;
			    }).collect(Collectors.joining());
			}
			ObjectMapper mapper = new ObjectMapper();
			carottaProductResDTO = mapper.readValue(response.getBody(), CarottaProductResDTO.class);
			carottaProductResDTO.setPageInfo(str);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return carottaProductResDTO;
    }

    /**
     * 获取商品总数
     * @return
     */
    public Integer getCarottaCount() {
        try {
			StringBuilder sb = new StringBuilder().append("https://")
			        .append(carottaKey)
			        .append(":")
			        .append(carottaPassword)
			        .append("@")
			        .append(carottaUrl)
			        .append("/admin/api/")
			        .append(carottaVersion)
			        .append("/products/count.json");
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");
			    log.info("--------------- Carotta获取商品总数异常{} ---------------", errorMessage);
			}
			return (Integer) JSONObject.parseObject(response.getBody()).get("count");
		} catch (Exception e) {
			e.printStackTrace();
		}
        return null;
    }

    /******************* end ********************/

    /******************* folli ********************/
    /**
     * 获取folli商品列表
     * @return
     */
    public FolliProductResDTO getFolliProductList(int pageNo, int pageSize) throws JsonProcessingException {
        FolliProductResDTO folliProductResDTO = null;
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.add("API-KEY", folliKey);
			headers.add("API-COMPANY", folliCompany);
			JSONObject param = new JSONObject();
			param.put("page_number",pageNo);
			param.put("page_size",pageSize);
			HttpEntity<JSONObject> requestEntity = new HttpEntity<>(param, headers);
			RestTemplate restTemplate = restTemplateConfig.restTemplate();
			ResponseEntity<String> response = restTemplate.exchange(folliUrl + "zcmk_listproducts", HttpMethod.GET, requestEntity, String.class);
			if (HttpStatus.OK != response.getStatusCode()) {
			    JSONObject message = JSONObject.parseObject(response.getBody());
			    String errorMessage = message.getString("error");
			    log.info("--------------- 获取folli商品列表异常{} ---------------", errorMessage);
			}
			ObjectMapper mapper = new ObjectMapper();
			FolliGoodsRes[] folliGoodsRes = mapper.readValue(response.getBody(), FolliGoodsRes[].class);
			folliProductResDTO = new FolliProductResDTO();
			folliProductResDTO.setProducts(Arrays.asList(folliGoodsRes));
		} catch (Exception e) {
			e.printStackTrace();
		}
        return folliProductResDTO;
    }

    /******************* end ********************/

    /******************* folli ********************/
    /**
     * 获取Delloglio商品列表
     * @return
     */
    public DelloglioProductResDTO getDelloglioProductList() throws IOException {
        DelloglioProductResDTO delloglioProductResDTO = null;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try {
            //1)    创建SAXParserFactory的对象
            SAXParserFactory spf=SAXParserFactory.newInstance();
            //2)    创建SAXParser对象 (解析器)
            SAXParser parser=spf.newSAXParser();
            URL url = new URL(delloglioUrl);
            conn=(HttpURLConnection)url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(1000 * 60 * 60 * 6);
            conn.setReadTimeout(1000 * 60 * 60 * 6);
            inputStream = conn.getInputStream();
            DelloglioXmlSaxHandler xmlSaxHandler = new DelloglioXmlSaxHandler();
            parser.parse(inputStream, xmlSaxHandler);
            delloglioProductResDTO = xmlSaxHandler.getDelloglioProductResDTO();
        } catch (Exception e) {
            log.error("---------拉取Delloglio商品列表失败------------");
        }finally {
            if(inputStream != null){
                inputStream.close();
            }
            if(conn != null){
                conn.disconnect();
            }
        }
        return delloglioProductResDTO;
    }

    /******************* end ********************/

    /******************* orange ********************/

    /**
     * 获取orange商品列表
     * @param page
     * @param limit
     * @return
     */
    public OrangeProductResDTO getOrangeProductList(int page, int limit) throws JsonProcessingException {
        OrangeProductResDTO orangeProductResDTO = null;
        try {
            StringBuilder sb = new StringBuilder().append(orangeUrl)
                    .append("item/get_item_list.do");
            JSONObject param = new JSONObject();
            param.put("appId",orangeAppId);
            param.put("limit",limit);
            param.put("page",page);
            String sign = DigestUtils.md5Hex(param.toJSONString()+orangeSecret).toUpperCase();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("SIGN", sign);
            HttpEntity<JSONObject> requestEntity = new HttpEntity<>(param, headers);
            RestTemplate restTemplate = restTemplateConfig.restTemplate();
            ResponseEntity<String> response = restTemplate.postForEntity(sb.toString(), requestEntity, String.class);
            if (HttpStatus.OK != response.getStatusCode()) {
                JSONObject message = JSONObject.parseObject(response.getBody());
                String errorMessage = message.getString("error");
                log.info("--------------- 获取orange商品列表异常{} ---------------", errorMessage);
            }
            ObjectMapper mapper = new ObjectMapper();
            orangeProductResDTO = mapper.readValue(response.getBody(), OrangeProductResDTO.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return orangeProductResDTO;
    }

    /******************* end ********************/

    /******************* pure ********************/

    /**
     * 获取pure商品列表
     * @return
     */
    public List<PureProductResDTO> getPureProducts() {
        List<PureProductResDTO> pureProductResDTOList = new ArrayList<>();
        try {
            StringBuilder sb = new StringBuilder().append(pureUrl)
                    .append("?").append(pureProducts);
            RestTemplate restTemplate = restTemplateConfig.restTemplate();
            ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
            if (HttpStatus.OK != response.getStatusCode()) {
                JSONObject message = JSONObject.parseObject(response.getBody());
                String errorMessage = message.getString("error");
                log.info("--------------- 获取pure商品列表异常{} ---------------", errorMessage);
            }
            pureProductResDTOList = JSONObject.parseArray(response.getBody(), PureProductResDTO.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return pureProductResDTOList;
    }

    /**
     * 获取pure商品库存
     * @return
     */
    public List<PureStockResDTO> getPureStocks() {
        List<PureStockResDTO> pureStockResDTOList = new ArrayList<>();
        try {
            StringBuilder sb = new StringBuilder().append(pureUrl)
                    .append("?").append(pureStocks);
            RestTemplate restTemplate = restTemplateConfig.restTemplate();
            ResponseEntity<String> response = restTemplate.getForEntity(sb.toString(), String.class);
            if (HttpStatus.OK != response.getStatusCode()) {
                JSONObject message = JSONObject.parseObject(response.getBody());
                String errorMessage = message.getString("error");
                log.info("--------------- 获取pure商品库存异常{} ---------------", errorMessage);
            }
            pureStockResDTOList = JSONObject.parseArray(response.getBody(), PureStockResDTO.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return pureStockResDTOList;
    }

    public List<PureImages> getPureImages() throws Exception {
        List<String> imageIdList = new ArrayList<>();
        List<String> productIdList = new ArrayList<>();
        RestTemplate restTemplate = restTemplateConfig.restTemplate();
        ResponseEntity<String> imageResponse = restTemplate.getForEntity("https://puresermoneta.com/api/images/products?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6", String.class);
        InputSource in = new InputSource(new StringReader(imageResponse.getBody()));
        in.setEncoding("UTF-8");
        SAXReader reader = new SAXReader();
        Document document = reader.read(in);
        Element rootElt = document.getRootElement();
        Element images = rootElt.element("images");
        List<Element> imageList = images.elements();
        imageList.forEach(e->imageIdList.add(e.attribute("id").getValue()));

        ResponseEntity<String> productResponse = restTemplate.getForEntity("https://puresermoneta.com/api/products?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6", String.class);
        InputSource productIn = new InputSource(new StringReader(productResponse.getBody()));
        in.setEncoding("UTF-8");
        Document productDocument = reader.read(productIn);
        Element productElt = productDocument.getRootElement();
        Element products = productElt.element("products");
        List<Element> productList = products.elements();
        productList.forEach(e->productIdList.add(e.attribute("id").getValue()));

        imageIdList.retainAll(productIdList);
        List<PureImages> pureImageList = new ArrayList<>();
        for (String id : imageIdList) {
            ResponseEntity<String> product = restTemplate.getForEntity("https://puresermoneta.com/api/products/"+id+"?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6", String.class);
            Document productRead = reader.read(new InputSource(new StringReader(product.getBody())));
            Element productElement = productRead.getRootElement().element("product");
            //ean13
            String ean13 = productElement.element("ean13").getText();
            //images
            List<Element> imagesElement = productElement.element("associations").element("images").elements();
            List<String> PicList = imagesElement.stream().map(e -> e.attribute("href").getValue()+"?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6").collect(Collectors.toList());
            JSONArray gallery = JSONArray.parseArray(JSON.toJSONString(PicList));
            PureImages pureImages = new PureImages();
            pureImages.setProductId(id).setEan13(ean13).setImages(gallery.toJSONString());
            pureImageList.add(pureImages);
            //combinations
            List<Element> combinations = productElement.element("associations").element("combinations").elements();
            for (Element combination : combinations) {
                ResponseEntity<String> combinationRes = restTemplate.getForEntity(combination.attribute("href").getValue()+"?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6", String.class);
                Document combinationRead = reader.read(new InputSource(new StringReader(combinationRes.getBody())));
                Element combinationElement = combinationRead.getRootElement().element("combination");
                String skuEan13 = combinationElement.element("ean13").getText();
                List<Element> skuImages = combinationElement.element("associations").element("images").elements();
                if(null != skuImages && skuImages.size() > 0){
                    List<String> skuPicList = skuImages.stream().map(e -> e.attribute("href").getValue()+"?ws_key=VGQWAJ785A5EWRIPFYE1IC3QV5PMLLS6").collect(Collectors.toList());
                    JSONArray skuPicJSONArray = JSONArray.parseArray(JSON.toJSONString(skuPicList));
                    PureImages skuPureImages = new PureImages();
                    skuPureImages.setProductId(id).setEan13(skuEan13).setImages(skuPicJSONArray.toJSONString());
                    pureImageList.add(skuPureImages);
                }
            }
        }
        return pureImageList;
    }

    /******************* end ********************/
}
